Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finish POSIX-native filesystem backend. #213

Merged
merged 4 commits into from
Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ project(vcpkg
HOMEPAGE_URL "https://github.com/microsoft/vcpkg"
LANGUAGES ${LANGUAGES}
)

include(cmake/utilities.cmake)

# =============
Expand All @@ -69,8 +70,6 @@ set(TLS12_DOWNLOAD_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/tls12-download.c")
# ========================

vcpkg_detect_compiler()
vcpkg_detect_standard_library()
vcpkg_detect_std_filesystem()

if(VCPKG_EMBED_GIT_SHA)
find_package(Git REQUIRED)
Expand Down Expand Up @@ -138,7 +137,6 @@ target_include_directories(vcpkglib PUBLIC include)

vcpkg_target_add_warning_options(vcpkglib)
target_compile_definitions(vcpkglib PUBLIC
VCPKG_USE_STD_FILESYSTEM=$<BOOL:${VCPKG_USE_STD_FILESYSTEM}>
VCPKG_VERSION=${VCPKG_VERSION}
VCPKG_BASE_VERSION=${VCPKG_BASE_VERSION}
)
Expand All @@ -147,10 +145,6 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(vcpkglib PRIVATE Threads::Threads)

if(VCPKG_CXXFS_LIBRARY)
target_link_libraries(vcpkglib PRIVATE ${VCPKG_CXXFS_LIBRARY})
endif()

if(MSVC)
get_target_property(_srcs vcpkglib SOURCES)

Expand Down
7 changes: 6 additions & 1 deletion azure-pipelines/Format-CxxCode.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
[CmdletBinding()]
$Root = Resolve-Path -LiteralPath "$PSScriptRoot/.."

$clangFormat = Get-Command 'clang-format' -ErrorAction 'SilentlyContinue'
$clangFormat = Get-Command 'clang-format-12' -ErrorAction 'SilentlyContinue'
if ($null -eq $clangFormat)
{
$clangFormat = Get-Command 'clang-format' -ErrorAction 'SilentlyContinue'
}

if ($null -ne $clangFormat)
{
$clangFormat = $clangFormat.Source
Expand Down
134 changes: 0 additions & 134 deletions cmake/utilities.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -50,140 +50,6 @@ If you would like to try anyway, pass --allowAppleClang to bootstrap.sh.
endif()
endfunction()

# Outputs to Cache: VCPKG_STANDARD_LIBRARY
function(vcpkg_detect_standard_library)
if(NOT DEFINED CACHE{VCPKG_STANDARD_LIBRARY})
include(CheckCXXSourceCompiles)

message(STATUS "Detecting the C++ standard library")

# note: since <ciso646> is the smallest header, generally it's used to get the standard library version
set(CMAKE_REQUIRED_QUIET ON)
check_cxx_source_compiles([[
#include <ciso646>
#if !defined(__GLIBCXX__)
#error "not libstdc++"
#endif
int main() {}
]]
_VCPKG_STANDARD_LIBRARY_LIBSTDCXX)
check_cxx_source_compiles([[
#include <ciso646>
#if !defined(_LIBCPP_VERSION)
#error "not libc++"
#endif
int main() {}
]]
_VCPKG_STANDARD_LIBRARY_LIBCXX)
check_cxx_source_compiles([[
#include <ciso646>
#if !defined(_MSVC_STL_VERSION) && !(defined(_MSC_VER) && _MSC_VER <= 1900)
#error "not MSVC stl"
#endif
int main() {}
]]
_VCPKG_STANDARD_LIBRARY_MSVC_STL)
if(_VCPKG_STANDARD_LIBRARY_LIBSTDCXX)
set(STANDARD_LIBRARY "libstdc++")
elseif(_VCPKG_STANDARD_LIBRARY_LIBCXX)
set(STANDARD_LIBRARY "libc++")
elseif(_VCPKG_STANDARD_LIBRARY_MSVC_STL)
set(STANDARD_LIBRARY "msvc-stl")
else()
message(FATAL_ERROR "Can't find which C++ runtime is in use")
endif()

set(VCPKG_STANDARD_LIBRARY ${STANDARD_LIBRARY}
CACHE STRING
"The C++ standard library in use; one of libstdc++, libc++, msvc-stl")

message(STATUS "Detecting the C++ standard library - ${VCPKG_STANDARD_LIBRARY}")
endif()
endfunction()

# Outputs to Cache: VCPKG_USE_STD_FILESYSTEM, VCPKG_CXXFS_LIBRARY
function(vcpkg_detect_std_filesystem)
vcpkg_detect_standard_library()

if(NOT DEFINED CACHE{VCPKG_USE_STD_FILESYSTEM})
include(CheckCXXSourceCompiles)

message(STATUS "Detecting how to use the C++ filesystem library")

set(CMAKE_REQUIRED_QUIET ON)
if(VCPKG_STANDARD_LIBRARY STREQUAL "libstdc++")
check_cxx_source_compiles([[
#include <ciso646>
#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 9
#error "libstdc++ after version 9 does not require -lstdc++fs"
#endif
int main() {}
]]
_VCPKG_REQUIRE_LINK_CXXFS)

check_cxx_source_compiles([[
#include <ciso646>
#if !defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE < 8
#error "libstdc++ before version 8 does not support <filesystem>"
#endif
int main() {}
]]
_VCPKG_USE_STD_FILESYSTEM)

if(_VCPKG_REQUIRE_LINK_CXXFS)
set(_VCPKG_CXXFS_LIBRARY "stdc++fs")
endif()
elseif(VCPKG_STANDARD_LIBRARY STREQUAL "libc++")
if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
# AppleClang never requires (or allows) -lc++fs, even with libc++ version 8.0.0
set(_VCPKG_CXXFS_LIBRARY OFF)
elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
# As above, not required on this platform (tested at least on 6.8)
set(_VCPKG_CXXFS_LIBRARY OFF)
else()
check_cxx_source_compiles([[
#include <ciso646>
#if _LIBCPP_VERSION >= 9000
#error "libc++ after version 9 does not require -lc++fs"
#endif
int main() {}
]]
_VCPKG_REQUIRE_LINK_CXXFS)

if(_VCPKG_REQUIRE_LINK_CXXFS)
set(_VCPKG_CXXFS_LIBRARY "c++fs")
endif()
endif()

# We don't support versions of libc++ < 7.0.0, and libc++ 7.0.0 has <filesystem>
set(_VCPKG_USE_STD_FILESYSTEM ON)
elseif(VCPKG_STANDARD_LIBRARY STREQUAL "msvc-stl")
set(_VCPKG_USE_STD_FILESYSTEM ON)
set(_VCPKG_CXXFS_LIBRARY OFF)
endif()

set(VCPKG_USE_STD_FILESYSTEM ${_VCPKG_USE_STD_FILESYSTEM}
CACHE BOOL
"Whether to use <filesystem>, as opposed to <experimental/filesystem>"
FORCE)
set(VCPKG_CXXFS_LIBRARY ${_VCPKG_CXXFS_LIBRARY}
CACHE STRING
"Library to link (if any) in order to use <filesystem>"
FORCE)

if(VCPKG_USE_STD_FILESYSTEM)
set(msg "<filesystem>")
else()
set(msg "<experimental/filesystem>")
endif()
if(VCPKG_CXXFS_LIBRARY)
set(msg "${msg} with -l${VCPKG_CXXFS_LIBRARY}")
endif()

message(STATUS "Detecting how to use the C++ filesystem library - ${msg}")
endif()
endfunction()

function(vcpkg_target_add_warning_options TARGET)
if(MSVC)
# either MSVC, or clang-cl
Expand Down
9 changes: 3 additions & 6 deletions include/vcpkg/base/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,8 @@ namespace vcpkg
enum class CopyOptions
{
none = 0,

existing_mask = 0xF,
skip_existing = 0x1,
overwrite_existing = 0x2,

recursive = 0x10,
};

struct Path
Expand Down Expand Up @@ -297,8 +293,9 @@ namespace vcpkg
void create_best_link(const Path& to, const Path& from, std::error_code& ec);
void create_best_link(const Path& to, const Path& from, LineInfo);

virtual void copy(const Path& source, const Path& destination, CopyOptions options, std::error_code& ec) = 0;
void copy(const Path& source, const Path& destination, CopyOptions options, LineInfo);
// copies regular files and directories, recursively.
virtual void copy_regular_recursive(const Path& source, const Path& destination, std::error_code& ec) = 0;
void copy_regular_recursive(const Path& source, const Path& destination, LineInfo);

virtual bool copy_file(const Path& source,
const Path& destination,
Expand Down
104 changes: 51 additions & 53 deletions src/vcpkg/base/files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,10 @@
#include <string>
#include <thread>

#if !defined(VCPKG_USE_STD_FILESYSTEM)
#error The build system must set VCPKG_USE_STD_FILESYSTEM.
#endif // !defined(VCPKG_USE_STD_FILESYSTEM)

#if VCPKG_USE_STD_FILESYSTEM
#if defined(_WIN32)
#include <filesystem>
#else
#include <experimental/filesystem>
#endif

#if VCPKG_USE_STD_FILESYSTEM
namespace stdfs = std::filesystem;
#else
namespace stdfs = std::experimental::filesystem;
#endif
#endif // _WIN32

namespace
{
Expand Down Expand Up @@ -82,28 +71,18 @@ namespace
li, Strings::concat(call_name, "(", Strings::join(", ", args.begin(), args.end()), "): ", ec.message()));
}

#if defined(_WIN32)
stdfs::copy_options convert_copy_options(CopyOptions options)
{
stdfs::copy_options result{};
const auto unpacked = static_cast<int>(options);

switch (unpacked & static_cast<int>(CopyOptions::existing_mask))
switch (options)
{
case static_cast<int>(CopyOptions::skip_existing): result |= stdfs::copy_options::skip_existing; break;
case static_cast<int>(CopyOptions::overwrite_existing):
result |= stdfs::copy_options::overwrite_existing;
break;
}

if (unpacked & static_cast<int>(CopyOptions::recursive))
{
result |= stdfs::copy_options::recursive;
case CopyOptions::none: return stdfs::copy_options::none;
case CopyOptions::skip_existing: return stdfs::copy_options::skip_existing;
case CopyOptions::overwrite_existing: return stdfs::copy_options::overwrite_existing;
default: Checks::unreachable(VCPKG_LINE_INFO);
}

return result;
}

#if defined(_WIN32)
FileType convert_file_type(stdfs::file_type type) noexcept
{
switch (type)
Expand All @@ -122,22 +101,11 @@ namespace
default: Checks::unreachable(VCPKG_LINE_INFO);
}
}
#endif // _WIN32

stdfs::path to_stdfs_path(const Path& utfpath)
{
#if defined(_WIN32)
return stdfs::path(Strings::to_utf16(utfpath.native()));
#else // ^^^ _WIN32 / !_WIN32 vvv
return stdfs::path(utfpath.native());
#endif // ^^^ !_WIN32
}
stdfs::path to_stdfs_path(const Path& utfpath) { return stdfs::path(Strings::to_utf16(utfpath.native())); }

#if defined(_WIN32)
Path from_stdfs_path(const stdfs::path& stdpath) { return Strings::to_utf8(stdpath.native()); }
#endif // ^^^ _WIN32

#if defined(_WIN32)
// The Win32 version of this implementation is effectively forked from
// https://github.com/microsoft/STL/blob/bd7adb4a932725f60ba096580c415616486ab64c/stl/inc/filesystem#L436
// converted to speak UTF-8 rather than UTF-16.
Expand Down Expand Up @@ -1539,10 +1507,10 @@ namespace vcpkg
}
}

void Filesystem::copy(const Path& source, const Path& destination, CopyOptions options, LineInfo li)
void Filesystem::copy_regular_recursive(const Path& source, const Path& destination, LineInfo li)
{
std::error_code ec;
this->copy(source, destination, options, ec);
this->copy_regular_recursive(source, destination, ec);
if (ec)
{
exit_filesystem_call_error(li, ec, __func__, {source, destination});
Expand Down Expand Up @@ -2568,13 +2536,45 @@ namespace vcpkg
}
#endif // _WIN32
}
virtual void copy(const Path& source,
const Path& destination,
CopyOptions options,
std::error_code& ec) override

virtual void copy_regular_recursive(const Path& source, const Path& destination, std::error_code& ec) override
{
stdfs::copy(to_stdfs_path(source), to_stdfs_path(destination), convert_copy_options(options), ec);
#if defined(_WIN32)
stdfs::copy(to_stdfs_path(source), to_stdfs_path(destination), stdfs::copy_options::recursive, ec);
#else // ^^^ _WIN32 // !_WIN32 vvv
ReadDirOp rd{source.c_str(), ec};
if (ec)
{
if (ec == std::errc::not_a_directory)
{
this->copy_file(source, destination, CopyOptions::none, ec);
}

return;
}

this->create_directory(destination, ec);
Path source_entry_name;
Path destination_entry_name;
const dirent* entry;
// the !ec check is either for the create_directory above on the first iteration, or for the most
// recent copy_file or copy_regular_recursive on subsequent iterations
while (!ec && (entry = rd.read(ec)))
{
source_entry_name = source / entry->d_name;
destination_entry_name = destination / entry->d_name;
if (get_d_type(entry) == PosixDType::Regular)
{
this->copy_file(source_entry_name, destination_entry_name, CopyOptions::none, ec);
}
else
{
this->copy_regular_recursive(source_entry_name, destination_entry_name, ec);
}
}
#endif // ^^^ !_WIN32
}

virtual bool copy_file(const Path& source,
const Path& destination,
CopyOptions options,
Expand Down Expand Up @@ -2605,10 +2605,8 @@ namespace vcpkg
return false;
}

auto masked_options =
static_cast<CopyOptions>(static_cast<int>(options) & static_cast<int>(CopyOptions::existing_mask));
int open_options = O_WRONLY | O_CREAT;
if (masked_options != CopyOptions::overwrite_existing)
if (options != CopyOptions::overwrite_existing)
{
// the standard wording suggests that we should create a file through a broken symlink which would
// forbid use of O_EXCL. However, implementations like boost::copy_file don't do this and doing it
Expand All @@ -2620,7 +2618,7 @@ namespace vcpkg
PosixFd destination_fd{destination.c_str(), open_options, open_mode, ec};
if (ec)
{
if (masked_options == CopyOptions::skip_existing && ec == std::errc::file_exists)
if (options == CopyOptions::skip_existing && ec == std::errc::file_exists)
{
ec.clear();
}
Expand All @@ -2647,7 +2645,7 @@ namespace vcpkg
return false;
}

if (masked_options == CopyOptions::overwrite_existing)
if (options == CopyOptions::overwrite_existing)
{
destination_fd.ftruncate(0, ec);
if (ec) return false;
Expand Down
Loading