├── .appveyor.yml ├── .ci ├── unix-build.sh └── unix-test.sh ├── .cirrus.yml ├── .clang-format ├── .clang-tidy ├── .drone.yml-disabled ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── build_cmake.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── GhcHelper.cmake └── config.cmake.in ├── examples ├── CMakeLists.txt ├── dir.cpp └── du.cpp ├── include └── ghc │ ├── filesystem.hpp │ ├── fs_fwd.hpp │ ├── fs_impl.hpp │ ├── fs_std.hpp │ ├── fs_std_fwd.hpp │ └── fs_std_impl.hpp └── test ├── CMakeLists.txt ├── catch.hpp ├── cmake └── ParseAndAddCatchTests.cmake ├── exception.cpp ├── filesystem_test.cpp ├── fwd_test.cpp ├── impl_test.cpp ├── multi1.cpp └── multi2.cpp /.appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - platform: x86 4 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 5 | generator: "Visual Studio 14 2015" 6 | compiler: msvc 7 | configuration: Release 8 | 9 | - platform: x64 10 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 11 | generator: "Visual Studio 14 2015 Win64" 12 | compiler: msvc 13 | configuration: Release 14 | 15 | - platform: x86 16 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 17 | generator: "Visual Studio 15 2017" 18 | compiler: msvc 19 | configuration: Release 20 | 21 | - platform: x64 22 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 23 | generator: "Visual Studio 15 2017 Win64" 24 | compiler: msvc 25 | configuration: Release 26 | 27 | - platform: x86 28 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 29 | generator: "Visual Studio 16 2019" 30 | compiler: msvc19 31 | configuration: Release 32 | arch: Win32 33 | 34 | - platform: x64 35 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 36 | generator: "Visual Studio 16 2019" 37 | compiler: msvc19 38 | configuration: Release 39 | arch: x64 40 | 41 | - platform: x86 42 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 43 | generator: "MinGW Makefiles" 44 | compiler: mingw 45 | TOOLCHAIN_PATH: C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32\bin 46 | CC: C:/mingw-w64/i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32/bin/gcc.exe 47 | CXX: C:/mingw-w64/i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32/bin/g++.exe 48 | configuration: Release 49 | 50 | - platform: x64 51 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 52 | generator: "MinGW Makefiles" 53 | compiler: mingw 54 | TOOLCHAIN_PATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin 55 | CC: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/gcc.exe 56 | CXX: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/g++.exe 57 | configuration: Release 58 | 59 | matrix: 60 | fast_finish: false 61 | 62 | init: 63 | - cmd: cmake --version 64 | - cmd: msbuild /version 65 | 66 | install: 67 | - cmd: reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1" 68 | - cmd: ren "C:\Program Files\Git\usr\bin\sh.exe" _sh.exe 69 | 70 | build_script: 71 | - mkdir build 72 | - cd build 73 | - if [%compiler%]==[msvc] cmake -G"%generator%" .. 74 | - if [%compiler%]==[msvc19] cmake -G"%generator%" -A "%arch%" .. 75 | - if [%compiler%]==[mingw] set PATH=%TOOLCHAIN_PATH%;%PATH% 76 | - if [%compiler%]==[mingw] cmake -G"%generator%" -DCMAKE_C_COMPILER=%CC% -DCMAKE_CXX_COMPILER=%CXX% -DCMAKE_SH=CMAKE_SH-NOTFOUND -DCMAKE_BUILD_TYPE=%configuration% .. 77 | - cmake --build . --config %configuration% 78 | 79 | test_script: 80 | - cd %APPVEYOR_BUILD_FOLDER%\build 81 | - set CTEST_OUTPUT_ON_FAILURE=1 82 | - ctest -C %configuration% 83 | - if exist "test\Release\std_filesystem_test.exe" test\Release\std_filesystem_test.exe & exit 0 84 | - cd .. 85 | 86 | -------------------------------------------------------------------------------- /.ci/unix-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir build && cd build 3 | cmake -DCMAKE_BUILD_TYPE=Release .. 4 | cmake --build . 5 | -------------------------------------------------------------------------------- /.ci/unix-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd build 3 | echo "Tests run as user: $USER" 4 | ctest -E Windows 5 | if [ -f "test/std_filesystem_test" ]; then 6 | test/std_filesystem_test || true 7 | fi 8 | -------------------------------------------------------------------------------- /.cirrus.yml: -------------------------------------------------------------------------------- 1 | freebsd_task: 2 | freebsd_instance: 3 | image_family: freebsd-14-0 4 | install_script: | 5 | pkg install -y cmake 6 | pw groupadd testgrp 7 | pw useradd testuser -g testgrp -w none -m 8 | chown -R testuser:testgrp . 9 | build_script: | 10 | sudo -u testuser .ci/unix-build.sh 11 | test_script: | 12 | sudo -u testuser .ci/unix-test.sh 13 | 14 | rockylinux8_task: 15 | container: 16 | image: docker.io/rockylinux:8 17 | install_script: | 18 | dnf group install -y "Development Tools" 19 | dnf install cmake -y 20 | build_script: | 21 | .ci/unix-build.sh 22 | test_script: | 23 | .ci/unix-test.sh 24 | 25 | rockylinux9_task: 26 | container: 27 | image: docker.io/rockylinux:9 28 | install_script: | 29 | dnf group install -y "Development Tools" 30 | dnf install cmake -y 31 | build_script: | 32 | .ci/unix-build.sh 33 | test_script: | 34 | .ci/unix-test.sh 35 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Chromium 4 | AccessModifierOffset: '-4' 5 | IndentWidth: '4' 6 | ColumnLimit: 256 7 | BreakBeforeBraces: Custom 8 | BraceWrapping: 9 | AfterClass: true 10 | AfterControlStatement: false 11 | AfterFunction: true 12 | AfterNamespace: false 13 | AfterObjCDeclaration: true 14 | AfterStruct: true 15 | AfterUnion: true 16 | BeforeCatch: true 17 | BeforeElse: true 18 | IndentBraces: false 19 | SplitEmptyFunction: true 20 | SplitEmptyRecord: true 21 | SplitEmptyNamespace: true 22 | BreakConstructorInitializers: BeforeComma 23 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 24 | IndentPPDirectives: None 25 | ... 26 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: -modernize-use-nodiscard 3 | ... 4 | -------------------------------------------------------------------------------- /.drone.yml-disabled: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: arm 3 | 4 | platform: 5 | os: linux 6 | arch: arm 7 | 8 | steps: 9 | - name: build 10 | image: alpine 11 | failure: ignore 12 | commands: 13 | - apk update 14 | - apk add --no-cache build-base cmake sudo 15 | - addgroup testgrp 16 | - adduser --disabled-password testuser testgrp 17 | - passwd testuser -u -d 18 | - chown -R testuser:testgrp . 19 | - sudo -u testuser .ci/unix-build.sh 20 | - sudo -u testuser .ci/unix-test.sh 21 | 22 | --- 23 | 24 | kind: pipeline 25 | name: arm64 26 | 27 | platform: 28 | os: linux 29 | arch: arm64 30 | 31 | steps: 32 | - name: build 33 | image: alpine 34 | failure: ignore 35 | commands: 36 | - apk update 37 | - apk add --no-cache build-base cmake 38 | - addgroup testgrp 39 | - adduser --disabled-password testuser testgrp 40 | - passwd testuser -u -d 41 | - chown -R testuser:testgrp . 42 | - su -c "./.ci/unix-build.sh" testuser 43 | - su -c "./.ci/unix-test.sh" testuser 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Detailed steps to reproduce the behavior. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Additional context** 17 | Add any other context about the problem here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/workflows/build_cmake.yml: -------------------------------------------------------------------------------- 1 | name: CMake Build Matrix 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | build: 7 | name: ${{ matrix.config.name }} 8 | runs-on: ${{ matrix.config.os }} 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | config: 13 | - name: "Ubuntu 22.04 GCC 11" 14 | os: ubuntu-22.04 15 | build_type: Release 16 | packages: ninja-build 17 | generator: Ninja 18 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 19 | cc: gcc 20 | cxx: g++ 21 | 22 | - name: "Ubuntu 22.04 Clang 13.0" 23 | os: ubuntu-22.04 24 | build_type: Release 25 | packages: ninja-build libc++-13-dev libc++abi-13-dev 26 | generator: Ninja 27 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 28 | cc: clang-13 29 | cxx: clang++-13 30 | 31 | - name: "Ubuntu 22.04 Clang 15.0" 32 | os: ubuntu-22.04 33 | build_type: Release 34 | packages: ninja-build libc++-15-dev libc++abi-15-dev 35 | generator: Ninja 36 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 37 | cc: clang-15 38 | cxx: clang++-15 39 | 40 | - name: "Ubuntu 22.04 GCC 11 coverage" 41 | os: ubuntu-22.04 42 | build_type: Debug 43 | packages: ninja-build lcov 44 | generator: Ninja 45 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 46 | cc: gcc 47 | cxx: g++ 48 | 49 | - name: "Ubuntu 20.04 GCC 9.3" 50 | os: ubuntu-20.04 51 | build_type: Release 52 | packages: ninja-build 53 | generator: Ninja 54 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 55 | cc: gcc 56 | cxx: g++ 57 | 58 | - name: "Ubuntu 20.04 Clang 10.0" 59 | os: ubuntu-20.04 60 | build_type: Release 61 | packages: ninja-build 62 | generator: Ninja 63 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 64 | cc: clang-10 65 | cxx: clang++-10 66 | 67 | - name: "Ubuntu 20.04 Clang 11.0" 68 | os: ubuntu-20.04 69 | build_type: Release 70 | packages: ninja-build clang-11 libc++-11-dev libc++abi-11-dev 71 | generator: Ninja 72 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 73 | cc: clang-11 74 | cxx: clang++-11 75 | 76 | - name: "Ubuntu 20.04 GCC 9.3 coverage" 77 | os: ubuntu-20.04 78 | build_type: Debug 79 | packages: ninja-build lcov 80 | generator: Ninja 81 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 82 | cc: gcc 83 | cxx: g++ 84 | 85 | - name: "Windows MSVC 2019" 86 | os: windows-2019 87 | build_type: Release 88 | packages: ninja 89 | generator: "Visual Studio 16 2019" 90 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 91 | cc: cl 92 | cxx: cl 93 | 94 | - name: "macOS 13 AppleClang" 95 | os: macos-13 96 | build_type: Release 97 | packages: ninja 98 | generator: Ninja 99 | compatibility: "cxx_std_11;cxx_std_17;cxx_std_20" 100 | cc: clang 101 | cxx: clang++ 102 | 103 | steps: 104 | - uses: actions/checkout@v2 105 | 106 | - name: print environment 107 | run: | 108 | echo github.event.action: ${{ github.event.action }} 109 | echo github.event_name: ${{ github.event_name }} 110 | 111 | - name: Install dependencies on Ubuntu 112 | if: startsWith(matrix.config.os, 'ubuntu') 113 | shell: bash 114 | run: | 115 | sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y 116 | sudo apt update 117 | sudo apt install ${{ matrix.config.packages }} 118 | 119 | - name: Install dependencies on windows 120 | if: startsWith(matrix.config.os, 'windows') 121 | run: | 122 | choco install ${{ matrix.config.packages }} 123 | 124 | - name: Install dependencies on macOS 125 | if: startsWith(matrix.config.os, 'macos') 126 | run: | 127 | brew install ${{ matrix.config.packages }} 128 | 129 | - name: Configure project 130 | shell: bash 131 | run: | 132 | export CC=${{ matrix.config.cc }} 133 | export CXX=${{ matrix.config.cxx }} 134 | ninja --version 135 | cmake --version 136 | mkdir build 137 | mkdir install 138 | if [[ "${{ matrix.config.build_type }}" == "Debug" ]]; then 139 | cmake -G "${{ matrix.config.generator }}" -S . -B build -DCMAKE_BUILD_TYPE=Debug -DGHC_COVERAGE=ON -DGHC_FILESYSTEM_TEST_COMPILE_FEATURES="${{ matrix.config.compatibility }}" -DCMAKE_INSTALL_PREFIX:PATH=install 140 | else 141 | cmake -G "${{ matrix.config.generator }}" -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DGHC_FILESYSTEM_TEST_COMPILE_FEATURES="${{ matrix.config.compatibility }}" -DCMAKE_INSTALL_PREFIX:PATH=install 142 | fi 143 | 144 | - name: Build project 145 | shell: bash 146 | run: | 147 | cmake --build build --config ${{ matrix.config.build_type }} 148 | 149 | - name: Run tests 150 | run: | 151 | cd build && ctest -C ${{ matrix.config.build_type }} 152 | 153 | - name: Collect coverage info 154 | if: startsWith(matrix.config.build_type, 'Debug') 155 | run: | 156 | cd build 157 | lcov --compat-libtool --directory . --capture --output-file coverage_output.info 158 | lcov --remove coverage_output.info '/usr/*' '*/c++/*' '*.h' '*/catch.hpp' -o coverage.info 159 | # sed -i 's|SF:/.*/filesystem/|SF:../|g' coverage.info 160 | 161 | - name: Upload coverage info 162 | if: startsWith(matrix.config.build_type, 'Debug') 163 | env: 164 | COVERALLS_DEBUG: true 165 | NODE_COVERALLS_DEBUG: 1 166 | uses: coverallsapp/github-action@master 167 | with: 168 | path-to-lcov: ${{ github.workspace }}/build/coverage.info 169 | github-token: ${{ secrets.GITHUB_TOKEN }} 170 | 171 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*build*/ 2 | .vs/ 3 | .vscode/ 4 | .idea/ 5 | *.swp 6 | *~ 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7.2) 2 | project( 3 | ghcfilesystem, 4 | VERSION 1.5.15 5 | ) 6 | 7 | if (POLICY CMP0077) 8 | cmake_policy(SET CMP0077 NEW) 9 | endif() 10 | if(POLICY CMP0110) 11 | cmake_policy(SET CMP0110 NEW) 12 | endif() 13 | 14 | if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) 15 | option(GHC_FILESYSTEM_BUILD_TESTING "Enable tests" ON) 16 | option(GHC_FILESYSTEM_BUILD_EXAMPLES "Build examples" ON) 17 | option(GHC_FILESYSTEM_WITH_INSTALL "With install target" ON) 18 | else() 19 | option(GHC_FILESYSTEM_BUILD_EXAMPLES "Build examples" OFF) 20 | option(GHC_FILESYSTEM_BUILD_TESTING "Enable tests" OFF) 21 | option(GHC_FILESYSTEM_WITH_INSTALL "With install target" OFF) 22 | endif() 23 | option(GHC_FILESYSTEM_BUILD_STD_TESTING "Enable STD tests" ${GHC_FILESYSTEM_BUILD_TESTING}) 24 | if(NOT DEFINED GHC_FILESYSTEM_TEST_COMPILE_FEATURES) 25 | set(GHC_FILESYSTEM_TEST_COMPILE_FEATURES ${CMAKE_CXX_COMPILE_FEATURES}) 26 | endif() 27 | 28 | if(NOT DEFINED CMAKE_CXX_STANDARD) 29 | set(CMAKE_CXX_STANDARD 11) 30 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 31 | if(NOT CYGWIN) 32 | set(CMAKE_CXX_EXTENSIONS OFF) 33 | endif() 34 | endif() 35 | if(CMAKE_CXX_STANDARD LESS 11) 36 | message(FATAL_ERROR "CMAKE_CXX_STANDARD is less than 11, ghc::filesystem only works with C++11 and above.") 37 | endif() 38 | if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) 39 | message(STATUS "System name: ${CMAKE_SYSTEM_NAME}") 40 | message(STATUS "Compiler ID: ${CMAKE_CXX_COMPILER_ID}") 41 | message(STATUS "CMAKE_CXX_COMPILE_FEATURES: ${CMAKE_CXX_COMPILE_FEATURES}") 42 | endif() 43 | 44 | add_library(ghc_filesystem INTERFACE) 45 | add_library(ghcFilesystem::ghc_filesystem ALIAS ghc_filesystem) 46 | target_include_directories(ghc_filesystem INTERFACE 47 | $ 48 | $) 49 | target_compile_options(ghc_filesystem INTERFACE "$<$:/utf-8>") 50 | target_compile_options(ghc_filesystem INTERFACE "$<$:/utf-8>") 51 | 52 | if(GHC_FILESYSTEM_BUILD_TESTING OR GHC_FILESYSTEM_BUILD_EXAMPLES) 53 | set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 54 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") 55 | include(GhcHelper) 56 | 57 | if(GHC_FILESYSTEM_BUILD_TESTING) 58 | enable_testing() 59 | add_subdirectory(test) 60 | endif() 61 | 62 | if(GHC_FILESYSTEM_BUILD_EXAMPLES) 63 | add_subdirectory(examples) 64 | endif() 65 | endif() 66 | 67 | if(GHC_FILESYSTEM_WITH_INSTALL) 68 | include(CMakePackageConfigHelpers) 69 | include(GNUInstallDirs) 70 | install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 71 | install(TARGETS ghc_filesystem EXPORT ghc_filesystem-targets) 72 | install(EXPORT ghc_filesystem-targets NAMESPACE ghcFilesystem:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem") 73 | export(EXPORT ghc_filesystem-targets NAMESPACE ghcFilesystem:: FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/ghc_filesystem-targets.cmake") 74 | configure_package_config_file( 75 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.cmake.in" 76 | "${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake" 77 | INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem" 78 | PATH_VARS CMAKE_INSTALL_INCLUDEDIR) 79 | write_basic_package_version_file( 80 | "${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config-version.cmake" 81 | VERSION ${PROJECT_VERSION} 82 | COMPATIBILITY SameMinorVersion 83 | ) 84 | install( 85 | FILES 86 | "${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake" 87 | "${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config-version.cmake" 88 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem" 89 | ) 90 | endif() 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Steffen Schümann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Supported Platforms](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows%20%7C%20FreeBSD-blue.svg) 2 | ![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg) 3 | [![CMake Build Matrix](https://github.com/gulrak/filesystem/actions/workflows/build_cmake.yml/badge.svg?branch=master)](https://github.com/gulrak/filesystem/actions/workflows/build_cmake.yml) 4 | [![Build Status](https://ci.appveyor.com/api/projects/status/t07wp3k2cddo0hpo/branch/master?svg=true)](https://ci.appveyor.com/project/gulrak/filesystem) 5 | [![Build Status](https://api.cirrus-ci.com/github/gulrak/filesystem.svg?branch=master)](https://cirrus-ci.com/github/gulrak/filesystem) 6 | [![Coverage Status](https://coveralls.io/repos/github/gulrak/filesystem/badge.svg?branch=master)](https://coveralls.io/github/gulrak/filesystem?branch=master) 7 | [![Latest Release Tag](https://img.shields.io/github/tag/gulrak/filesystem.svg)](https://github.com/gulrak/filesystem/tree/v1.5.14) 8 | 9 | 10 | 11 | 12 | * [Filesystem](#filesystem) 13 | * [Motivation](#motivation) 14 | * [Why the namespace GHC?](#why-the-namespace-ghc) 15 | * [Platforms](#platforms) 16 | * [Tests](#tests) 17 | * [Usage](#usage) 18 | * [Downloads](#downloads) 19 | * [Using it as Single-File-Header](#using-it-as-single-file-header) 20 | * [Using it as Forwarding-/Implementation-Header](#using-it-as-forwarding-implementation-header) 21 | * [Git Submodule and CMake](#git-submodule-and-cmake) 22 | * [Versioning](#versioning) 23 | * [Documentation](#documentation) 24 | * [`ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream`](#ghcfilesystemifstream--ghcfilesystemofstream--ghcfilesystemfstream) 25 | * [`ghc::filesystem::u8arguments`](#ghcfilesystemu8arguments) 26 | * [Differences](#differences) 27 | * [LWG Defects](#lwg-defects) 28 | * [Not Implemented on C++ before C++17](#not-implemented-on-c-before-c17) 29 | * [Differences in API](#differences-in-api) 30 | * [Differences of Specific Interfaces](#differences-of-specific-interfaces) 31 | * [Differences in Behavior](#differences-in-behavior) 32 | * [fs.path (ref)](#fspath--ref-) 33 | * [Open Issues](#open-issues) 34 | * [Windows](#windows) 35 | * [Symbolic Links on Windows](#symbolic-links-on-windows) 36 | * [Permissions](#permissions) 37 | * [Release Notes](#release-notes) 38 | 39 | 40 | # Filesystem 41 | 42 | This is a header-only single-file `std::filesystem` compatible helper library, 43 | based on the C++17 and C++20 specs, but implemented for C++11, C++14, C++17 or C++20 44 | (tightly following the C++17 standard with very few documented exceptions). It is currently tested on 45 | macOS 10.12/10.14/10.15/11.6, Windows 10, Ubuntu 18.04, Ubuntu 20.04, CentOS 7, CentOS 8, FreeBSD 12, 46 | Alpine ARM/ARM64 Linux and Solaris 10 but should work on other systems too, as long as you have 47 | at least a C++11 compatible compiler. It should work with Android NDK, Emscripten and I even 48 | had reports of it being used on iOS (within sandboxing constraints) and with v1.5.6 there 49 | is experimental support for QNX. The support of Android NDK, Emscripten, QNX, and since 1.5.14 50 | GNU/Hurd and Haiku is not backed up by automated testing but PRs and bug reports are welcome 51 | for those too and they are reported to work. 52 | It is of course in its own namespace `ghc::filesystem` to not interfere with a regular `std::filesystem` 53 | should you use it in a mixed C++17 environment (which is possible). 54 | 55 | *Test coverage is well above 90%, and starting with v1.3.6 and in v1.5.0 56 | more time was invested in benchmarking and optimizing parts of the library. I'll try 57 | to continue to optimize some parts and refactor others, striving 58 | to improve it as long as it doesn't introduce additional C++17/C++20 compatibility 59 | issues. Feedback is always welcome. Simply open an issue if you see something missing 60 | or wrong or not behaving as expected and I'll comment.* 61 | 62 | 63 | ## Motivation 64 | 65 | I'm often in need of filesystem functionality, mostly `fs::path`, but directory 66 | access too, and when beginning to use C++11, I used that language update 67 | to try to reduce my third-party dependencies. I could drop most of what 68 | I used, but still missed some stuff that I started implementing for the 69 | fun of it. Originally I based these helpers on my own coding- and naming 70 | conventions. When C++17 was finalized, I wanted to use that interface, 71 | but it took a while, to push myself to convert my classes. 72 | 73 | The implementation is closely based on chapter 30.10 from the C++17 standard 74 | and a draft close to that version is 75 | [Working Draft N4687](https://github.com/cplusplus/draft/raw/master/papers/n4687.pdf). 76 | It is from after the standardization of C++17 but it contains the latest filesystem 77 | interface changes compared to the 78 | [Working Draft N4659](https://github.com/cplusplus/draft/raw/master/papers/n4659.pdf). 79 | Staring with v1.4.0, when compiled using C++20, it adapts to the changes according to path sorting order 80 | and `std::u8string` handling from [Working Draft N4860](https://isocpp.org/files/papers/N4860.pdf). 81 | 82 | I want to thank the people working on improving C++, I really liked how the language 83 | evolved with C++11 and the following standards. Keep on the good work! 84 | 85 | ## Why the namespace GHC? 86 | If you ask yourself, what `ghc` is standing for, it is simply 87 | `gulraks helper classes`, yeah, I know, not very imaginative, but I wanted a 88 | short namespace and I use it in some of my private classes (so **it has nothing 89 | to do with Haskell**, sorry for the name clash). 90 | 91 | ## Platforms 92 | 93 | `ghc::filesystem` is developed on macOS but CI tested on macOS, Windows, 94 | various Linux Distributions, FreeBSD and starting with v1.5.12 on Solaris. 95 | It should work on any of these with a C++11-capable compiler. Also there are some 96 | checks to hopefully better work on Android, but as I currently don't test with the 97 | Android NDK, I wouldn't call it a supported platform yet, same is valid for using 98 | it with Emscripten. It is now part of the detected platforms, I fixed the obvious 99 | issues and ran some tests with it, so it should be fine. All in all, I don't see it 100 | replacing `std::filesystem` where full C++17 or C++20 is available, it doesn't try 101 | to be a "better" `std::filesystem`, just an almost drop-in if you can't use it 102 | (with the exception of the UTF-8 preference). 103 | 104 | :information_source: **Important:** _This implementation is following the ["UTF-8 Everywhere" philosophy](https://utf8everywhere.org/) in that all 105 | `std::string` instances will be interpreted the same as `std::u8string` encoding 106 | wise and as being in UTF-8. The `std::u16string` will be seen as UTF-16. See *Differences in API* 107 | for more information._ 108 | 109 | Unit tests are currently run with: 110 | 111 | * macOS 10.12: Xcode 9.2 (clang-900.0.39.2), GCC 9.2, Clang 9.0, macOS 10.13: Xcode 10.1, macOS 10.14: Xcode 11.2, macOS 10.15: Xcode 11.6, Xcode 12.4 112 | * Windows: Visual Studio 2017, Visual Studio 2015, Visual Studio 2019, MinGW GCC 6.3 (Win32), GCC 7.2 (Win64), Cygwin GCC 10.2 (no CI yet) 113 | * Linux (Ubuntu): GCC (5.5, 6.5, 7.4, 8.3, 9.2), Clang (5.0, 6.0, 7.1, 8.0, 9.0) 114 | * ~~Linux (Alpine ARM/ARM64): GCC 9.2.0~~ (The Drone build scripts stopped working, 115 | as they where a contribution, I couldn't figure out what went wrong, any help appreciated.) 116 | * FreeBSD: Clang 8.0 117 | * Solaris: GCC 5.5 118 | 119 | 120 | ## Tests 121 | 122 | The header comes with a set of unit-tests and uses [CMake](https://cmake.org/) 123 | as a build tool and [Catch2](https://github.com/catchorg/Catch2) as test framework. 124 | All tests are registered with in CMake, so the [ctest](https://cmake.org/cmake/help/latest/manual/ctest.1.html) 125 | commando can be used to run the tests. 126 | 127 | All tests against this implementation should succeed, depending on your environment 128 | it might be that there are some warnings, e.g. if you have no rights to create 129 | Symlinks on Windows or at least the test thinks so, but these are just informative. 130 | 131 | To build the tests from inside the project directory under macOS or Linux just: 132 | 133 | ```cpp 134 | mkdir build 135 | cd build 136 | cmake -DCMAKE_BUILD_TYPE=Debug .. 137 | make 138 | ctest 139 | ``` 140 | 141 | This generates the test binaries that run the tests and the last command executes 142 | them. 143 | 144 | If the default compiler is a GCC 8 or newer, or Clang 7 or newer, it 145 | additionally tries to build a version of the test binary compiled against GCCs/Clangs 146 | `std::filesystem` implementation, named `std_filesystem_test` 147 | as an additional test of conformance. Ideally all tests should compile and 148 | succeed with all filesystem implementations, but in reality, there are 149 | some differences in behavior, sometimes due to room for interpretation in 150 | in the standard, and there might be issues in these implementations too. 151 | 152 | 153 | ## Usage 154 | 155 | ### Downloads 156 | 157 | The latest release version is [v1.5.14](https://github.com/gulrak/filesystem/tree/v1.5.14) and 158 | source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.5.14). 159 | 160 | The latest pre-native-backend version is [v1.4.0](https://github.com/gulrak/filesystem/tree/v1.4.0) and 161 | source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.4.0). 162 | 163 | The latest pre-C++20-support release version is [v1.3.10](https://github.com/gulrak/filesystem/tree/v1.3.10) and 164 | source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.3.10). 165 | 166 | Currently only the latest minor release version receives bugfixes, so if possible, 167 | you should use the latest release. 168 | 169 | ### Using it as Single-File-Header 170 | 171 | As `ghc::filesystem` is at first a header-only library, it should be enough to copy the header 172 | or the `include/ghc` directory into your project folder or point your include path to this place and 173 | simply include the `filesystem.hpp` header (or `ghc/filesystem.hpp` if you use the subdirectory). 174 | 175 | Everything is in the namespace `ghc::filesystem`, so one way to use it only as 176 | a fallback could be: 177 | 178 | ```cpp 179 | #if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) 180 | // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus 181 | // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ 182 | #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html 183 | #define GHC_USE_STD_FS 184 | 185 | // Old Apple OSs don't support std::filesystem, though the header is available at compile 186 | // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, 187 | // and watchOS 6.0. 188 | #ifdef __APPLE__ 189 | #include 190 | // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS 191 | // released after std::filesystem, where std::filesystem is always available. 192 | // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) 193 | #if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ 194 | || __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ 195 | || __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ 196 | || __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 197 | #undef GHC_USE_STD_FS 198 | #endif 199 | #endif 200 | #endif 201 | #endif 202 | 203 | #ifdef GHC_USE_STD_FS 204 | #include 205 | namespace fs = std::filesystem; 206 | #else 207 | #include "filesystem.hpp" 208 | namespace fs = ghc::filesystem; 209 | #endif 210 | ``` 211 | 212 | If you want to also use the `fstream` wrapper with `path` support as fallback, 213 | you might use: 214 | 215 | ```cpp 216 | #if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) 217 | // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus 218 | // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ 219 | #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html 220 | #define GHC_USE_STD_FS 221 | 222 | // Old Apple OSs don't support std::filesystem, though the header is available at compile 223 | // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, 224 | // and watchOS 6.0. 225 | #ifdef __APPLE__ 226 | #include 227 | // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS 228 | // released after std::filesystem, where std::filesystem is always available. 229 | // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) 230 | #if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ 231 | || __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ 232 | || __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ 233 | || __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 234 | #undef GHC_USE_STD_FS 235 | #endif 236 | #endif 237 | #endif 238 | #endif 239 | 240 | #ifdef GHC_USE_STD_FS 241 | #include 242 | namespace fs { 243 | using namespace std::filesystem; 244 | using ifstream = std::ifstream; 245 | using ofstream = std::ofstream; 246 | using fstream = std::fstream; 247 | } 248 | #else 249 | #include "filesystem.hpp" 250 | namespace fs { 251 | using namespace ghc::filesystem; 252 | using ifstream = ghc::filesystem::ifstream; 253 | using ofstream = ghc::filesystem::ofstream; 254 | using fstream = ghc::filesystem::fstream; 255 | } 256 | #endif 257 | ``` 258 | 259 | Now you have e.g. `fs::ofstream out(somePath);` and it is either the wrapper or 260 | the C++17 `std::ofstream`. 261 | 262 | :information_source: **Be aware, as a header-only library, it is not hiding the fact, that it 263 | uses system includes, so they "pollute" your global namespace. Use the 264 | forwarding-/implementation-header based approach (see below) to avoid this. 265 | For Windows it needs `Windows.h` and it might be a good idea to define 266 | `WIN32_LEAN_AND_MEAN` or `NOMINMAX` prior to including `filesystem.hpp` or 267 | `fs_std.hpp` headers to reduce pollution of your global namespace and compile 268 | time. They are not defined by `ghc::filesystem` to allow combination with contexts 269 | where the full `Windows.h`is needed, e.g. for UI elements.** 270 | 271 | :information_source: **Hint:** There is an additional header named `ghc/fs_std.hpp` that implements this 272 | dynamic selection of a filesystem implementation, that you can include 273 | instead of `ghc/filesystem.hpp` when you want `std::filesystem` where 274 | available and `ghc::filesystem` where not. 275 | 276 | 277 | ### Using it as Forwarding-/Implementation-Header 278 | 279 | Alternatively, starting from v1.1.0 `ghc::filesystem` can also be used by 280 | including one of two additional wrapper headers. These allow to include 281 | a forwarded version in most places (`ghc/fs_fwd.hpp`) while hiding the 282 | implementation details in a single cpp file that includes `ghc/fs_impl.hpp` to 283 | implement the needed code. Using `ghc::filesystem` this way makes sure 284 | system includes are only visible from inside the cpp file, all other places are clean. 285 | 286 | Be aware, that it is currently not supported to hide the implementation 287 | into a Windows-DLL, as a DLL interface with C++ standard templates in interfaces 288 | is a different beast. If someone is willing to give it a try, I might integrate 289 | a PR but currently working on that myself is not a priority. 290 | 291 | If you use the forwarding/implementation approach, you can still use the dynamic 292 | switching like this: 293 | 294 | ```cpp 295 | #if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) 296 | // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus 297 | // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ 298 | #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html 299 | #define GHC_USE_STD_FS 300 | 301 | // Old Apple OSs don't support std::filesystem, though the header is available at compile 302 | // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, 303 | // and watchOS 6.0. 304 | #ifdef __APPLE__ 305 | #include 306 | // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS 307 | // released after std::filesystem, where std::filesystem is always available. 308 | // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) 309 | #if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ 310 | || __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ 311 | || __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ 312 | || __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 313 | #undef GHC_USE_STD_FS 314 | #endif 315 | #endif 316 | #endif 317 | #endif 318 | 319 | #ifdef GHC_USE_STD_FS 320 | #include 321 | namespace fs { 322 | using namespace std::filesystem; 323 | using ifstream = std::ifstream; 324 | using ofstream = std::ofstream; 325 | using fstream = std::fstream; 326 | } 327 | #else 328 | #include "fs_fwd.hpp" 329 | namespace fs { 330 | using namespace ghc::filesystem; 331 | using ifstream = ghc::filesystem::ifstream; 332 | using ofstream = ghc::filesystem::ofstream; 333 | using fstream = ghc::filesystem::fstream; 334 | } 335 | #endif 336 | ``` 337 | 338 | and in the implementation hiding cpp, you might use (before any include that includes `ghc/fs_fwd.hpp` 339 | to take precedence: 340 | 341 | ```cpp 342 | #if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) 343 | // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus 344 | // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ 345 | #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html 346 | #define GHC_USE_STD_FS 347 | 348 | // Old Apple OSs don't support std::filesystem, though the header is available at compile 349 | // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, 350 | // and watchOS 6.0. 351 | #ifdef __APPLE__ 352 | #include 353 | // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS 354 | // released after std::filesystem, where std::filesystem is always available. 355 | // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) 356 | #if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ 357 | || __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ 358 | || __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ 359 | || __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 360 | #undef GHC_USE_STD_FS 361 | #endif 362 | #endif 363 | #endif 364 | #endif 365 | 366 | #ifndef GHC_USE_STD_FS 367 | #include "fs_impl.hpp" 368 | #endif 369 | ``` 370 | 371 | :information_source: **Hint:** There are additional helper headers, named `ghc/fs_std_fwd.hpp` and 372 | `ghc/fs_std_impl.hpp` that use this technique, so you can simply include them 373 | if you want to dynamically select the filesystem implementation. 374 | 375 | 376 | 377 | ### Git Submodule and CMake 378 | 379 | Starting from v1.1.0, it is possible to add `ghc::filesystem` 380 | as a git submodule, add the directory to your `CMakeLists.txt` with 381 | `add_subdirectory()` and then simply use `target_link_libraries(your-target ghc_filesystem)` 382 | to ensure correct include path that allow `#include ` 383 | to work. 384 | 385 | The `CMakeLists.txt` offers a few options to customize its behavior: 386 | 387 | * `GHC_FILESYSTEM_BUILD_TESTING` - Compile tests, default is `OFF` when used as 388 | a submodule, else `ON`. 389 | * `GHC_FILESYSTEM_BUILD_EXAMPLES` - Compile the examples, default is `OFF` when used as 390 | a submodule, else `ON`. 391 | * `GHC_FILESYSTEM_WITH_INSTALL` - Add install target to build, default is `OFF` when used as 392 | a submodule, else `ON`. 393 | * `GHC_FILESYSTEM_BUILD_STD_TESTING` - Compile `std_filesystem_test`, the variant of 394 | the test suite running against `std::filesystem`, defaulting to `GHC_FILESYSTEM_BUILD_TESTING`. 395 | This is only done if the compiler is detected as being able to do it. 396 | * `GHC_FILESYSTEM_TEST_COMPILE_FEATURES` can be set to a list of features to override 397 | `CMAKE_CXX_COMPILE_FEATURES` when the detection of C++17 or C++20 for additional tests 398 | is not working (e.g. `cxx_std_20` to enforce building a `filesystem_test_cpp20` with C++20). 399 | 400 | ### Bazel 401 | 402 | Please use [hedronvision/bazel-cc-filesystem-backport](https://github.com/hedronvision/bazel-cc-filesystem-backport), which will automatically set everything up for you. 403 | 404 | ### Versioning 405 | 406 | There is a version macro `GHC_FILESYSTEM_VERSION` defined in case future changes 407 | might make it needed to react on the version, but I don't plan to break anything. 408 | It's the version as decimal number `(major * 10000 + minor * 100 + patch)`. 409 | 410 | :information_source: **Note:** Only even patch versions will be used for releases 411 | and odd patch version will only be used for in between commits while working on 412 | the next version. 413 | 414 | 415 | ## Documentation 416 | 417 | There is almost no documentation in this release, as any `std::filesystem` 418 | documentation would work, besides the few differences explained in the next 419 | section. So you might head over to https://en.cppreference.com/w/cpp/filesystem 420 | for a description of the components of this library. 421 | 422 | When compiling with C++11, C++14 or C++17, the API is following the C++17 423 | standard, where possible, with the exception that `std::string_view` parameters 424 | are only supported on C++17. When Compiling with C++20, `ghc::filesysytem` 425 | defaults to the C++20 API, with the `char8_t` and `std::u8string` interfaces 426 | and the deprecated `fs::u8path` factory method. 427 | 428 | :information_source: **Note:** If the C++17 API should be enforced even in C++20 mode, 429 | use the define `GHC_FILESYSTEM_ENFORCE_CPP17_API`. 430 | Even then it is possible to create `fws::path` from `std::u8string` but 431 | `fs::path::u8string()` and `fs::path::generic_u8string()` return normal 432 | UTF-8 encoded `std::string` instances, so code written for C++17 could 433 | still work with `ghc::filesystem` when compiled with C++20. 434 | 435 | The only additions to the standard are documented here: 436 | 437 | 438 | ### `ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream` 439 | 440 | These are simple wrappers around `std::ifstream`, `std::ofstream` and `std::fstream`. 441 | They simply add an `open()` method and a constructor with an `ghc::filesystem::path` 442 | argument as the `fstream` variants in C++17 have them. 443 | 444 | ### `ghc::filesystem::u8arguments` 445 | 446 | This is a helper class that currently checks for UTF-8 encoding on non-Windows platforms but on Windows it 447 | fetches the command line arguments as Unicode strings from the OS with 448 | 449 | ```cpp 450 | ::CommandLineToArgvW(::GetCommandLineW(), &argc) 451 | ``` 452 | 453 | and then converts them to UTF-8, and replaces `argc` and `argv`. It is a guard-like 454 | class that reverts its changes when going out of scope. 455 | 456 | So basic usage is: 457 | 458 | ```cpp 459 | namespace fs = ghc::filesystem; 460 | 461 | int main(int argc, char* argv[]) 462 | { 463 | fs::u8arguments u8guard(argc, argv); 464 | if(!u8guard.valid()) { 465 | std::cerr << "Bad encoding, needs UTF-8." << std::endl; 466 | exit(EXIT_FAILURE); 467 | } 468 | 469 | // now use argc/argv as usual, they have utf-8 encoding on windows 470 | // ... 471 | 472 | return 0; 473 | } 474 | ``` 475 | 476 | That way `argv` is UTF-8 encoded as long as the scope from `main` is valid. 477 | 478 | **Note:** On macOS, while debugging under Xcode the code currently will return 479 | `false` as Xcode starts the application with `US-ASCII` as encoding, no matter what 480 | encoding is actually used and even setting `LC_ALL` in the product scheme doesn't 481 | change anything. I still need to investigate this. 482 | 483 | 484 | ## Differences 485 | 486 | As this implementation is based on existing code from my private helper 487 | classes, it derived some constraints of it. Starting from v1.5.0 most of the 488 | differences between this and the standard C++17/C++20 API where removed. 489 | 490 | 491 | ### LWG Defects 492 | 493 | This implementation has switchable behavior for the LWG defects 494 | [#2682](https://wg21.cmeerw.net/lwg/issue2682), 495 | [#2935](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2935), 496 | [#2936](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2936) and 497 | [#2937](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2937). 498 | The currently selected behavior (starting from v1.4.0) is following 499 | [#2682](https://wg21.cmeerw.net/lwg/issue2682), [#2936](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2936), 500 | [#2937](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2937) but 501 | not following [#2935](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2935), 502 | as I feel it is a bug to report no error on a `create_directory()` or `create_directories()` 503 | where a regular file of the same name prohibits the creation of a directory and forces 504 | the user of those functions to double-check via `fs::is_directory` if it really worked. 505 | The more intuitive approach to directory creation of treating a file with that name as an 506 | error is also advocated by the newer paper 507 | [WG21 P1164R0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1164r0.pdf), the revision 508 | P1161R1 was agreed upon on Kona 2019 meeting [see merge](https://github.com/cplusplus/draft/issues/2703) 509 | and GCC by now switched to following its proposal 510 | ([GCC #86910](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86910)). 511 | 512 | ### Not Implemented on C++ before C++17 513 | 514 | ```cpp 515 | // methods in ghc::filesystem::path: 516 | path& operator+=(basic_string_view x); 517 | int compare(basic_string_view s) const; 518 | ``` 519 | 520 | These are not implemented under C++11 and C++14, as there is no 521 | `std::basic_string_view` available and I did want to keep this 522 | implementation self-contained and not write a full C++17-upgrade for 523 | C++11/14. Starting with v1.1.0 these are supported when compiling 524 | `ghc::filesystem` under C++17 of C++20. 525 | 526 | Starting with v1.5.2 `ghc::filesystem` will try to allow the use of 527 | `std::experimental::basic_string_view` where it detects is availability. 528 | Additionally if you have a `basic_string_view` compatible c++11 529 | implementation it can be used instead of `std::basic_string_view` 530 | by defining `GHC_HAS_CUSTOM_STRING_VIEW` and importing the 531 | implementation into the `ghc::filesystem` namespace with: 532 | 533 | ```cpp 534 | namespace ghc { 535 | namespace filesystem { 536 | using my::basic_string_view; 537 | } 538 | } 539 | ``` 540 | 541 | before including the filesystem header. 542 | 543 | ### Differences in API 544 | 545 | To not depend on any external third party libraries and still stay portable and 546 | compact, this implementation is following the ["UTF-8 Everywhere" philosophy](https://utf8everywhere.org/) in that all 547 | `std::string` instances will be interpreted the same as `std::u8string` encoding 548 | wise and as being in UTF-8. The `std::u16string` will be seen as UTF-16 and `std::u32string` will be 549 | seen as Unicode codepoints. Depending on the size of `std::wstring` characters, it will handle 550 | `std::wstring` as being UTF-16 (e.g. Windows) or `char32_t` Unicode codepoints 551 | (currently all other platforms). 552 | 553 | #### Differences of Specific Interfaces 554 | 555 | Starting with v1.5.0 `ghc::filesystem` is following the C++17 standard in 556 | using `wchar_t` and `std::wstring` on Windows as the types internally used 557 | for path representation. It is still possible to get the old behavior by defining 558 | `GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE` and get `filesystem::path::string_type` as 559 | `std::string` and `filesystem::path::value_type` as `wchar_t`. 560 | 561 | If you need to call some Windows API, with v1.5.0 and above, simply 562 | use the W-variant of the Windows-API call (e.g. `GetFileAttributesW(p.c_str())`). 563 | 564 | :information_source: **Note:** _When using the old behavior by defining 565 | `GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE`, use the `path::wstring()` member 566 | (e.g. `GetFileAttributesW(p.wstring().c_str())`). This gives you the 567 | Unicode variant independent of the `UNICODE` macro and makes sharing code 568 | between Windows, Linux and macOS easier and works with `std::filesystem` and 569 | `ghc::filesystem`._ 570 | 571 | ```cpp 572 | std::string path::u8string() const; 573 | std::string path::generic_u8string() const; 574 | vs. 575 | std::u8string path::u8string() const; 576 | std::u8string path::generic_u8string() const; 577 | ``` 578 | 579 | The return type of these two methods is depending on the used C++ standard 580 | and if `GHC_FILESYSTEM_ENFORCE_CPP17_API` is defined. On C++11, C++14 and 581 | C++17 or when `GHC_FILESYSTEM_ENFORCE_CPP17_API` is defined, the return 582 | type is `std::string`, and on C++20 without the define it is `std::u8string`. 583 | 584 | ### Differences in Behavior 585 | 586 | I created a wiki entry about quite a lot of [behavioral differences](https://github.com/gulrak/filesystem/wiki/Differences-to-Standard-Filesystem-Implementations) 587 | between different `std::filesystem` implementations that could result in a 588 | mention here, but this readme only tries to address the design choice 589 | differences between `ghc::filesystem` and those. I try to update the wiki page 590 | from time to time. 591 | 592 | Any additional observations are welcome! 593 | 594 | #### fs.path ([ref](https://en.cppreference.com/w/cpp/filesystem/path)) 595 | 596 | Since v1.5.0 the complete inner mechanics of this implementations `fs::path` 597 | where changed to the _native_ format as the internal representation. 598 | Creating any mixed slash `fs::path` object under Windows (e.g. with `"C:\foo/bar"`) 599 | will lead clean path with `"C:\foo\bar"` via `native()` and `"C:/foo/bar"` via 600 | `generic_string()` API. On all platforms redundant additional separators are 601 | removed, even if this is not enforced by the standard and other implementations 602 | mostly not do this. 603 | 604 | Additionally this implementation follows the standards suggestion to handle 605 | posix paths of the form `"//host/path"` and USC path on windows also as having 606 | a root-name (e.g. `"//host"`). The GCC implementation didn't choose to do that 607 | while testing on Ubuntu 18.04 and macOS with GCC 8.1.0 or Clang 7.0.0. This difference 608 | will show as warnings under `std::filesystem`. This leads to a change in the 609 | algorithm described in the standard for `operator/=(path& p)` where any path 610 | `p` with `p.is_absolute()` will degrade to an assignment, while this implementation 611 | has the exception where `*this == *this.root_name()` and `p == preferred_separator` 612 | a normal append will be done, to allow: 613 | 614 | ```cpp 615 | fs::path p1 = "//host/foo/bar/file.txt"; 616 | fs::path p2; 617 | for (auto p : p1) p2 /= p; 618 | ASSERT(p1 == p2); 619 | ``` 620 | 621 | For all non-host-leading paths the behavior will match the one described by 622 | the standard. 623 | 624 | 625 | ## Open Issues 626 | 627 | ### Windows 628 | 629 | #### Symbolic Links on Windows 630 | 631 | As symbolic links on Windows, while being supported more or less since 632 | Windows Vista (with some strict security constraints) and fully since some earlier 633 | build of Windows 10, when "Developer Mode" is activated, are at time of writing 634 | (2018) rarely used, still they are supported wiit th this implementation. 635 | 636 | #### Permissions 637 | 638 | The Windows ACL permission feature translates badly to the POSIX permission 639 | bit mask used in the interface of C++17 filesystem. The permissions returned 640 | in the `file_status` are therefore currently synthesized for the `user`-level 641 | and copied to the `group`- and `other`-level. There is still some potential 642 | for more interaction with the Windows permission system, but currently setting 643 | or reading permissions with this implementation will most certainly not lead 644 | to the expected behavior. 645 | 646 | 647 | ## Release Notes 648 | 649 | ### v1.5.15 (wip) 650 | 651 | * Fix for [#166](https://github.com/gulrak/filesystem/issues/166), 652 | `extension()` did return non empty result for the directory name 653 | `".."` 654 | 655 | ### [v1.5.14](https://github.com/gulrak/filesystem/releases/tag/v1.5.14) 656 | 657 | * Pull request [#163](https://github.com/gulrak/filesystem/pull/163), build 658 | support for Haiku (also fixes [#159](https://github.com/gulrak/filesystem/issues/159)) 659 | * Pull request [#162](https://github.com/gulrak/filesystem/pull/162), fix for 660 | directory iterator treating all files subsequent to a symlink as symlink 661 | on Windows 662 | * Pull request [#161](https://github.com/gulrak/filesystem/pull/161), the 663 | CMake alias `ghcFilesystem::ghc_filesystem` is now set unconditionally 664 | * Fix for [#160](https://github.com/gulrak/filesystem/issues/160), the cmake 665 | config now only sets install targets by default if the project is no 666 | subproject, as documented 667 | * Fix for [#157](https://github.com/gulrak/filesystem/issues/157), suppress 668 | C4191 warning on MSVC for GetProcAddress casts 669 | * Fix for [#156](https://github.com/gulrak/filesystem/issues/156), on POSIX 670 | `stem()`, `filename()` and `extension()` of `fs::path` would return wrong 671 | result if a colon was in the filename 672 | * Pull request [#154](https://github.com/gulrak/filesystem/pull/145), build 673 | support for GNU/Hurd 674 | * Pull request [#153](https://github.com/gulrak/filesystem/pull/153), fixed 675 | `fs::last_write_time(path, time, ec)` setter on iOS, tvOS and watchOS 676 | * Fix for [#151](https://github.com/gulrak/filesystem/issues/156), 677 | `fs::directory_entry::refresh()` now, consistently with `status()` will not 678 | throw on symlinks to non-existing targets, but make the entry have 679 | `file_type::not_found` as the type 680 | * Pull request [#149](https://github.com/gulrak/filesystem/pull/149), add 681 | version to CMake project and export it 682 | * Fix for [#146](https://github.com/gulrak/filesystem/issues/146), handle `EINTR` 683 | on POSIX directory iteration and file copy to avoid errors on network 684 | filesystems 685 | * Pull request [#145](https://github.com/gulrak/filesystem/pull/145), fix for 686 | Y2038 bug in timeToFILETIME on Windows 687 | * Pull request [#144](https://github.com/gulrak/filesystem/pull/144), `fs::copy_file()` 688 | now also copies the permissions 689 | * Pull request [#143](https://github.com/gulrak/filesystem/pull/143), fix 690 | for `fs::copy_file()` ignoring the `skip_existing` option. 691 | 692 | ### [v1.5.12](https://github.com/gulrak/filesystem/releases/tag/v1.5.12) 693 | 694 | * Fix for [#142](https://github.com/gulrak/filesystem/issues/142), removed need 695 | for `GHC_NO_DIRENT_D_TYPE` on systems that don't support `dirent::d_type` and 696 | fixed build configuration and tests to support Solaris as new platform. 697 | * Pull request [#138](https://github.com/gulrak/filesystem/pull/138), if the 698 | platform uses the POSIX backend and has no `PATH_MAX`, one is defined. 699 | * Pull request [#137](https://github.com/gulrak/filesystem/pull/137), update 700 | of Catch2 to version v2.13.7 701 | * Added macOS 11 to the automatically tested platforms. 702 | 703 | ### [v1.5.10](https://github.com/gulrak/filesystem/releases/tag/v1.5.10) 704 | 705 | * Pull request [#136](https://github.com/gulrak/filesystem/pull/136), the Windows 706 | implementation used some unnecessary expensive shared pointer for resource 707 | management and these where replaced by a dedicated code. 708 | * Fix for [#132](https://github.com/gulrak/filesystem/issues/132), pull request 709 | [#135](https://github.com/gulrak/filesystem/pull/135), `fs::remove_all` now 710 | just deletes symbolic links instead of following them. 711 | * Pull request [#133](https://github.com/gulrak/filesystem/pull/133), fix for 712 | `fs::space` where a numerical overflow could happen in a multiplication. 713 | * Replaced _travis-ci.org_ with GitHub Workflow for the configurations: 714 | Ubuntu 20.04: GCC 9.3, Ubuntu 18.04: GCC 7.5, GCC 8.4, macOS 10.15: Xcode 12.4, 715 | Windows 10: Visual Studio 2019 716 | 717 | ### [v1.5.8](https://github.com/gulrak/filesystem/releases/tag/v1.5.8) 718 | 719 | * Fix for [#125](https://github.com/gulrak/filesystem/issues/124), where 720 | `fs::create_directories` on Windows no longer breaks on long filenames. 721 | 722 | ### [v1.5.6](https://github.com/gulrak/filesystem/releases/tag/v1.5.6) 723 | 724 | * Fix for [#124](https://github.com/gulrak/filesystem/issues/124), 725 | `ghc::filesystem` treated mounted folder/volumes erroneously as symlinks, 726 | leading `fs::canonical` to fail on paths containing those. 727 | * Fix for [#122](https://github.com/gulrak/filesystem/issues/122), incrementing 728 | the `recursive_directory_iterator` will not try to enter dead symlinks. 729 | * Fix for [#121](https://github.com/gulrak/filesystem/issues/121), on Windows 730 | backend the `fs::remove` failed when the path pointed to a read-only entry, 731 | see also ([microsoft/STL#1511](https://github.com/microsoft/STL/issues/1511)) 732 | for the corresponding issue in `std::fs` on windows. 733 | * Fix for [#119](https://github.com/gulrak/filesystem/issues/119), added missing 734 | support for char16_t and char32_t and on C++20 char8_t literals. 735 | * Pull request [#118](https://github.com/gulrak/filesystem/pull/118), when 736 | running tests as root, disable tests that would not work. 737 | * Pull request [#117](https://github.com/gulrak/filesystem/pull/117), added 738 | checks to tests to detect the clang/libstdc++ combination. 739 | * Fix for [#116](https://github.com/gulrak/filesystem/issues/116), internal 740 | macro `GHC_NO_DIRENT_D_TYPE` allows os detection to support systems without 741 | the `dirent.d_type` member, experimental first QNX compile support as 742 | initial use case, fixed issue with filesystems returning DT_UNKNOWN 743 | (e.g. reiserfs). 744 | * Pull request [#115](https://github.com/gulrak/filesystem/pull/115), added 745 | `string_view` support when clang with libstdc++ is detected. 746 | * Fix for [#114](https://github.com/gulrak/filesystem/issues/114), for macOS 747 | the pre-Catalina deployment target detection worked only if `` 748 | was included before `` or ``/``. 749 | * Fix for [#113](https://github.com/gulrak/filesystem/issues/113), the use of 750 | standard chapter numbers was misleading since C++17 and C++20 `std::filesystem` 751 | features are supported, and was replaced by the tag-like chapter names that 752 | stay (mostly) consistent over the versions. 753 | 754 | ### [v1.5.4](https://github.com/gulrak/filesystem/releases/tag/v1.5.4) 755 | 756 | * Pull request [#112](https://github.com/gulrak/filesystem/pull/112), lots 757 | of cleanup work on the readme, thanks! 758 | * Enhancement for [#111](https://github.com/gulrak/filesystem/issues/111), 759 | further optimization of directory iteration, performance for 760 | `recursive_directory_iterator` over large trees now somewhere between 761 | libc++ and libstdc++. 762 | * Enhancement for [#110](https://github.com/gulrak/filesystem/issues/110), 763 | `ghc::filesystem` now has preliminary support for Cygwin. Changes where 764 | made to allow the tests to compile and run successfully (tested with GCC 765 | 10.2.0), feedback and additional PRs welcome as it is currently not 766 | part of the CI configuration. 767 | * Pull request [#109](https://github.com/gulrak/filesystem/pull/109), various 768 | spelling errors in error messages and comments fixed. 769 | * Pull request [#108](https://github.com/gulrak/filesystem/pull/108), old 770 | style casts removed. 771 | * Fix for [#107](https://github.com/gulrak/filesystem/issues/107), the error 772 | handling for status calls was suppressing errors on symlink targets. 773 | * Pull request [#106](https://github.com/gulrak/filesystem/pull/106), fixed 774 | detection of AppleClang for compile options. 775 | * Pull request [#105](https://github.com/gulrak/filesystem/pull/105), added 776 | option `GHC_FILESYSTEM_BUILD_STD_TESTING` to override additional build of 777 | `std::filesystem` versions of the tests for comparison and the possibility 778 | to use `GHC_FILESYSTEM_TEST_COMPILE_FEATURES` to prefill the used compile 779 | features defaulting to `CMAKE_CXX_COMPILE_FEATURES` when not given. 780 | 781 | ### [v1.5.2](https://github.com/gulrak/filesystem/releases/tag/v1.5.2) 782 | 783 | * Enhancement [#104](https://github.com/gulrak/filesystem/issues/104), 784 | on POSIX backend: optimized reuse of status information and reduced 785 | `directory_entry` creation leads to about 20%-25% in tests with 786 | `recursive_directory_iterator` over a larger directory tree. 787 | * Pull request [#103](https://github.com/gulrak/filesystem/pull/103), `wchar_t` 788 | was not in the list of supported char types on non-Windows backends. 789 | * Pull request [#102](https://github.com/gulrak/filesystem/pull/102), improved 790 | `string_view` support makes use of `` or `` 791 | when available, and allows use of custom `basic_string_view` implementation 792 | when defining `GHC_HAS_CUSTOM_STRING_VIEW` and importing the string view 793 | into the `ghc::filesystem` namespace before including filesystem header. 794 | * Pull request [#101](https://github.com/gulrak/filesystem/pull/101), fix for 795 | [#100](https://github.com/gulrak/filesystem/issues/100), append and concat 796 | type of operations on path called redundant conversions. 797 | * Pull request [#98](https://github.com/gulrak/filesystem/pull/98), on older 798 | linux variants (GCC 7/8), the comparison `std::filesystem` tests now link 799 | with `-lrt` to avoid issues. 800 | * Fix for [#97](https://github.com/gulrak/filesystem/issues/97), on BTRFS the 801 | test case for `fs::hard_link_count` failed due to the filesystems behavior, 802 | the test case was adapted to take that into account. 803 | * Pull request [#96](https://github.com/gulrak/filesystem/pull/96), the export 804 | attribute defines `GHC_FS_API` and `GHC_FS_API_CLASS` are now honored when when 805 | set from outside to allow override of behavior. 806 | * Fix for [#95](https://github.com/gulrak/filesystem/issues/95), the syntax for 807 | disabling the deprecated warning in tests in MSVC was wrong. 808 | * Pull request [#93](https://github.com/gulrak/filesystem/pull/93), now the 809 | CMake configuration file is configured and part of the `make install` files. 810 | 811 | ### [v1.5.0](https://github.com/gulrak/filesystem/releases/tag/v1.5.0) 812 | 813 | * Fix for [#91](https://github.com/gulrak/filesystem/issues/91), the way 814 | the CMake build options `GHC_FILESYSTEM_BUILD_TESTING`, `GHC_FILESYSTEM_BUILD_EXAMPLES` 815 | and `GHC_FILESYSTEM_WITH_INSTALL` where implemented, prohibited setting them 816 | from a parent project when using this via `add_subdirectory`, this fix 817 | allows to set them again. 818 | * Major refactoring for [#90](https://github.com/gulrak/filesystem/issues/90), 819 | the way, the Windows version of `fs::path` was originally created from the 820 | POSIX based implementation was, by adaption of the incoming and outgoing 821 | strings. This resulted in a mutable cache inside `fs::path`on Windows, that 822 | was inherently not thread-safe, even for `const` methods. 823 | To not add additional patches to a suboptimal solution, this time I reworked 824 | the `path` code to now store _native_ path-representation. This changed a 825 | lot of code, but when combined with `wchar_t` as `value_type` helped to avoid 826 | lots of conversion for calls to Win-API.
827 | As interfaces where changed, it had to be released in a new minor version. 828 | The set of refactorings resulted in the following changes: 829 | * `fs::path::native()` and `fs::path::c_str()` can now be `noexcept` as the 830 | standard mandates 831 | * On Windows `wchar_t` is now the default for `fs::path::value_type` and 832 | `std::wstring` is the default for `fs::path::string_type`. 833 | * This allows the implementation to call Win-API without allocating 834 | conversions 835 | * Thread-safety on `const` methods of `fs::path` is no longer an issue 836 | * Some code could be simplified during this refactoring 837 | * Automatic prefixing of long path on Windows can now be disabled with 838 | defining `GHC_WIN_DISABLE_AUTO_PREFIXES`, for all other types of prefixes 839 | or namespaces the behavior follows that of MSVC `std::filesystem::path` 840 | * In case the old `char`/`std::string` based approach for Windows is still 841 | needed, it can be activated with `GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE` 842 | * Enhancement for [#89](https://github.com/gulrak/filesystem/issues/89), `fs::file_status` 843 | now supports `operator==` introduced in `std::filesystem` with C++20. 844 | * Refactoring for [#88](https://github.com/gulrak/filesystem/issues/88), `fs::path::parent_path()` 845 | had a performance issue, as it was still using a loop based approach to recreate 846 | the parent from elements. This created lots of temporaries and was too slow 847 | especially on long paths. 848 | 849 | ### [v1.4.0](https://github.com/gulrak/filesystem/releases/tag/v1.4.0) 850 | 851 | * Enhancements for [#71](https://github.com/gulrak/filesystem/issues/71), when compiled with C++20: 852 | * `char8_t` and `std::u8string` are supported where `Source` is the parameter type 853 | * `fs::path::u8string()` and `fs::path::generic_u8string()` now return a `std::u8string` 854 | * The _spaceship operator_ `<=>` is now supported for `fs::path` 855 | * With the define `GHC_FILESYSTEM_ENFORCE_CPP17_API` `ghc::filesystem` will fall back 856 | to the old `fs::path::u8string()` and `fs::path::generic_u8string()` API if preferred 857 | * Bugfix for `fs::proximate(p, ec)` where the internal call to `fs::current_path()` was not 858 | using the `error_code` variant, throwing possible exceptions instead of setting `ec`. 859 | * Enhancement `LWG_2936_BEHAVIOUR` is now on by default. 860 | * Some cleanup work to reduce preprocessor directives for better readability and remove unneeded 861 | template specializations. 862 | 863 | ### [v1.3.10](https://github.com/gulrak/filesystem/releases/tag/v1.3.10) 864 | 865 | * Fix for [#81](https://github.com/gulrak/filesystem/issues/81), fixed issues with 866 | handling `Source` parameters that are string views. 867 | * Fix for [#79](https://github.com/gulrak/filesystem/issues/79), the bit operations 868 | for filesystem bitmasks that should be are now `constexpr`. 869 | 870 | ### [v1.3.8](https://github.com/gulrak/filesystem/releases/tag/v1.3.8) 871 | 872 | * Refactoring for [#78](https://github.com/gulrak/filesystem/issues/78), the dynamic 873 | switching helper includes are now using `__MAC_OS_X_VERSION_MIN_REQUIRED` to 874 | ensure that `std::filesystem` is only selected on macOS if the deployment target is 875 | at least Catalina. 876 | * Bugfix for [#77](https://github.com/gulrak/filesystem/issues/77), the `directory_iterator` 877 | and the `recursive_directory_iterator` had an issue with the `skip_permission_denied` 878 | option, that leads to the inability to skip SIP protected folders on macOS. 879 | * Enhancement for [#76](https://github.com/gulrak/filesystem/issues/76), `_MSVC_LANG` is 880 | now used when available, additionally to `__cplusplus`, in the helping headers to 881 | allow them to work even when `/Zc:__cplusplus` is not used. 882 | * Bugfix for [#75](https://github.com/gulrak/filesystem/issues/75), NTFS reparse points 883 | to mapped volumes where handled incorrect, leading to `false` on `fs::exists` or 884 | not-found-errors on `fs::status`. Namespaced paths are not filtered anymore. 885 | 886 | ### [v1.3.6](https://github.com/gulrak/filesystem/releases/tag/v1.3.6) 887 | 888 | * Pull request [#74](https://github.com/gulrak/filesystem/pull/74), on Windows symlink 889 | evaluation used the wrong reparse struct information and was not handling the case 890 | of relative paths well, thanks for the contribution. 891 | * Refactoring for [#73](https://github.com/gulrak/filesystem/issues/73), enhanced performance 892 | in path handling. the changes lead to much fewer path/string creations or copies, speeding 893 | up large directory iteration or operations on many path instances. 894 | * Bugfix for [#72](https://github.com/gulrak/filesystem/issues/72), the `TestAllocator` in 895 | `filesystem_test.cpp` was completed to fulfill the requirements to build on CentOS 7 with 896 | `devtoolset-9`. CentOS 7 and CentOS 8 are now part of the CI builds. 897 | * Bugfix for [#70](https://github.com/gulrak/filesystem/issues/70), root names are now case 898 | insensitive on Windows. This fix also adds the new behavior switch `LWG_2936_BEHAVIOUR` 899 | that allows to enable post C++17 `fs::path::compare` behavior, where the comparison is as 900 | if it was an element wise path comparison as described in 901 | [LWG 2936](https://cplusplus.github.io/LWG/issue2936) and C++20 `[fs.path.compare]`. 902 | It is default off in v1.3.6 and will be default starting from v1.4.0 as it changes ordering. 903 | 904 | ### [v1.3.4](https://github.com/gulrak/filesystem/releases/tag/v1.3.4) 905 | 906 | * Pull request [#69](https://github.com/gulrak/filesystem/pull/69), use `wchar_t` versions of 907 | `std::fstream` from `ghc::filesystem::fstream` wrappers on Windows if using GCC with libc++. 908 | * Bugfix for [#68](https://github.com/gulrak/filesystem/issues/68), better handling of 909 | permission issues for directory iterators when using `fs::directory_options::skip_permission_denied` 910 | and initial support for compilation with emscripten. 911 | * Refactoring for [#66](https://github.com/gulrak/filesystem/issues/63), unneeded shared_ptr guards 912 | where removed and the file handles closed where needed to avoid unnecessary allocations. 913 | * Bugfix for [#63](https://github.com/gulrak/filesystem/issues/63), fixed issues on Windows 914 | with clang++ and C++17. 915 | * Pull request [#62](https://github.com/gulrak/filesystem/pull/62), various fixes for 916 | better Android support, thanks for the PR 917 | * Pull request [#61](https://github.com/gulrak/filesystem/pull/61), `ghc::filesystem` now 918 | supports use in projects with disabled exceptions. API signatures using exceptions for 919 | error handling are not available in this mode, thanks for the PR (this resolves 920 | [#60](https://github.com/gulrak/filesystem/issues/60) and 921 | [#43](https://github.com/gulrak/filesystem/issues/43)) 922 | 923 | ### [v1.3.2](https://github.com/gulrak/filesystem/releases/tag/v1.3.2) 924 | 925 | * Bugfix for [#58](https://github.com/gulrak/filesystem/issues/58), on MinGW the 926 | compilation could fail with an error about an undefined `ERROR_FILE_TOO_LARGE` 927 | constant. 928 | * Bugfix for [#56](https://github.com/gulrak/filesystem/issues/58), `fs::lexically_relative` 929 | didn't ignore trailing slash on the base parameter, thanks for PR 930 | [#57](https://github.com/gulrak/filesystem/pull/57). 931 | * Bugfix for [#55](https://github.com/gulrak/filesystem/issues/55), `fs::create_directories` 932 | returned `true` when nothing needed to be created, because the directory already existed. 933 | * Bugfix for [#54](https://github.com/gulrak/filesystem/issues/54), `error_code` 934 | was not reset, if cached result was returned. 935 | * Pull request [#53](https://github.com/gulrak/filesystem/pull/53), fix for wrong 936 | handling of leading whitespace when reading `fs::path` from a stream. 937 | * Pull request [#52](https://github.com/gulrak/filesystem/pull/52), an ARM Linux 938 | target is now part of the CI infrastructure with the service of Drone CI. 939 | * Pull request [#51](https://github.com/gulrak/filesystem/pull/51), FreeBSD is now 940 | part of the CI infrastructure with the service of Cirrus CI. 941 | * Pull request [#50](https://github.com/gulrak/filesystem/pull/50), adaptive cast to 942 | `timespec` fields to avoid warnings. 943 | 944 | ### [v1.3.0](https://github.com/gulrak/filesystem/releases/tag/v1.3.0) 945 | 946 | * **Important: `ghc::filesystem` is re-licensed from BSD-3-Clause to MIT license.** (see 947 | [#47](https://github.com/gulrak/filesystem/issues/47)) 948 | * Pull request [#46](https://github.com/gulrak/filesystem/pull/46), suppresses 949 | unused parameter warning on Android. 950 | * Bugfix for [#44](https://github.com/gulrak/filesystem/issues/44), fixes 951 | for warnings from newer Xcode versions. 952 | 953 | ### [v1.2.10](https://github.com/gulrak/filesystem/releases/tag/v1.2.10) 954 | 955 | * The Visual Studio 2019 compiler, GCC 9.2 and Clang 9.0 where added to the 956 | CI configuration. 957 | * Bugfix for [#41](https://github.com/gulrak/filesystem/issues/41), `fs::rename` 958 | on Windows didn't replace an existing regular file as required by the standard, 959 | but gave an error. New tests and a fix as provided in the issue was implemented. 960 | * Bugfix for [#39](https://github.com/gulrak/filesystem/issues/39), for the 961 | forwarding use via `fs_fwd.hpp` or `fs_std_fwd.hpp` there was a use of 962 | `DWORD` in the forwarding part leading to an error if `Windows.h` was not 963 | included before the header. The tests were changed to give an error in that 964 | case too and the useage of `DWORD` was removed. 965 | * Bugfix for [#38](https://github.com/gulrak/filesystem/issues/38), casting the 966 | return value of `GetProcAddress` gave a warning with `-Wcast-function-type` 967 | on MSYS2 and MinGW GCC 9 builds. 968 | 969 | ### [v1.2.8](https://github.com/gulrak/filesystem/releases/tag/v1.2.8) 970 | 971 | * Pull request [#30](https://github.com/gulrak/filesystem/pull/30), the 972 | `CMakeLists.txt` will automatically exclude building examples and tests when 973 | used as submodule, the configuration options now use a prefixed name to 974 | reduce risk of conflicts. 975 | * Pull request [#24](https://github.com/gulrak/filesystem/pull/24), install 976 | target now creates a `ghcFilesystemConfig.cmake` in 977 | `${CMAKE_INSTALL_LIBDIR}/cmake/ghcFilesystem` for `find_package` that 978 | exports a target as `ghcFilesystem::ghc_filesystem`. 979 | * Pull request [#31](https://github.com/gulrak/filesystem/pull/31), fixes 980 | `error: redundant redeclaration of 'constexpr' static data member` deprecation 981 | warning in C++17 mode. 982 | * Pull request [#32](https://github.com/gulrak/filesystem/pull/32), fixes 983 | old-style-cast warnings. 984 | * Pull request [#34](https://github.com/gulrak/filesystem/pull/34), fixes 985 | [TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) situation 986 | on `fs::create_directories`, thanks for the PR! 987 | * Feature [#35](https://github.com/gulrak/filesystem/issues/35), new CMake 988 | option to add an install target `GHC_FILESYSTEM_WITH_INSTALL` that is 989 | defaulted to OFF if `ghc::filesystem` is used via `add_subdirectory`. 990 | * Bugfix for [#33](https://github.com/gulrak/filesystem/issues/33), fixes 991 | an issue with `fs::path::lexically_normal()` that leaves a trailing separator 992 | in case of a resulting path ending with `..` as last element. 993 | * Bugfix for [#36](https://github.com/gulrak/filesystem/issues/36), warnings 994 | on Xcode 11.2 due to unhelpful references in path element iteration. 995 | 996 | ### [v1.2.6](https://github.com/gulrak/filesystem/releases/tag/v1.2.6) 997 | 998 | * Pull request [#23](https://github.com/gulrak/filesystem/pull/23), tests and 999 | examples can now be disabled in CMake via setting `BUILD_TESTING` and 1000 | `BUILD_EXAMPLES` to `NO`, `OFF` or `FALSE`. 1001 | * Pull request [#25](https://github.com/gulrak/filesystem/pull/25), 1002 | missing specialization for construction from `std::string_view` when 1003 | available was added. 1004 | * Additional test case when `std::string_view` is available. 1005 | * Bugfix for [#27](https://github.com/gulrak/filesystem/issues/27), the 1006 | `fs::path::preferred_separator` declaration was not compiling on pre 1007 | C++17 compilers and no test accessed it, to show the problem. Fixed 1008 | it to an construction C++11 compiler should accept and added a test that 1009 | is successful on all combinations tested. 1010 | * Bugfix for [#29](https://github.com/gulrak/filesystem/issues/29), stricter 1011 | warning settings where chosen and resulting warnings where fixed. 1012 | 1013 | ### [v1.2.4](https://github.com/gulrak/filesystem/releases/tag/v1.2.4) 1014 | 1015 | * Enabled stronger warning switches and resulting fixed issues on GCC and MinGW 1016 | * Bugfix for #22, the `fs::copy_options` where not forwarded from `fs::copy` to 1017 | `fs::copy_file` in one of the cases. 1018 | 1019 | ### [v1.2.2](https://github.com/gulrak/filesystem/releases/tag/v1.2.2) 1020 | 1021 | * Fix for ([#21](https://github.com/gulrak/filesystem/pull/21)), when compiling 1022 | on Alpine Linux with musl instead of glibc, the wrong `strerror_r` signature 1023 | was expected. The complex preprocessor define mix was dropped in favor of 1024 | the usual dispatch by overloading a unifying wrapper. 1025 | 1026 | ### [v1.2.0](https://github.com/gulrak/filesystem/releases/tag/v1.2.0) 1027 | 1028 | * Added MinGW 32/64 and Visual Studio 2015 builds to the CI configuration. 1029 | * Fixed additional compilation issues on MinGW. 1030 | * Pull request ([#13](https://github.com/gulrak/filesystem/pull/13)), set 1031 | minimum required CMake version to 3.7.2 (as in Debian 8). 1032 | * Pull request ([#14](https://github.com/gulrak/filesystem/pull/14)), added 1033 | support for a make install target. 1034 | * Bugfix for ([#15](https://github.com/gulrak/filesystem/issues/15)), the 1035 | forward/impl way of using `ghc::filesystem` missed a `` include 1036 | in the windows case. 1037 | * Bugfix for ([#16](https://github.com/gulrak/filesystem/issues/16)), 1038 | VS2019 didn't like the old size dispatching in the utf8 decoder, so it 1039 | was changed to a sfinae based approach. 1040 | * New feature ([#17](https://github.com/gulrak/filesystem/issues/17)), optional 1041 | support for standard conforming `wchar_t/std::wstring` interface when 1042 | compiling on Windows with defined `GHC_WIN_WSTRING_STRING_TYPE`, this is 1043 | default when using the `ghc/fs_std*.hpp` header, to enhance compatibility. 1044 | * New feature ([#18](https://github.com/gulrak/filesystem/issues/18)), optional 1045 | filesystem exceptions/errors on Unicode errors with defined 1046 | `GHC_RAISE_UNICODE_ERRORS` (instead of replacing invalid code points or 1047 | UTF-8 encoding errors with the replacement character `U+FFFD`). 1048 | * Pull request ([#20](https://github.com/gulrak/filesystem/pull/20)), fix for 1049 | file handle leak in `fs::copy_file`. 1050 | * Coverage now checked in CI (~95% line coverage). 1051 | 1052 | ### [v1.1.4](https://github.com/gulrak/filesystem/releases/tag/v1.1.4) 1053 | 1054 | * Additional Bugfix for ([#12](https://github.com/gulrak/filesystem/issues/12)), 1055 | error in old unified `readdir/readdir_r` code of `fs::directory_iterator`; 1056 | as `readdir_r` is now deprecated, I decided to drop it and the resulting 1057 | code is much easier, shorter and due to more refactoring faster 1058 | * Fix for crashing unit tests against MSVC C++17 `std::filesystem` 1059 | * Travis-CI now additionally test with Xcode 10.2 on macOS 1060 | * Some minor refactorings 1061 | 1062 | ### [v1.1.2](https://github.com/gulrak/filesystem/releases/tag/v1.1.2) 1063 | 1064 | * Bugfix for ([#11](https://github.com/gulrak/filesystem/issues/11)), 1065 | `fs::path::lexically_normal()` had some issues with `".."`-sequences. 1066 | * Bugfix for ([#12](https://github.com/gulrak/filesystem/issues/12)), 1067 | `fs::recursive_directory_iterator` could run into endless loops, 1068 | the methods depth() and pop() had issues and the copy behavior and 1069 | `input_iterator_tag` conformance was broken, added tests 1070 | * Restructured some CMake code into a macro to ease the support for 1071 | C++17 `std::filesystem` builds of tests and examples for interoperability 1072 | checks. 1073 | * Some fixes on Windows tests to ease interoperability test runs. 1074 | * Reduced noise on `fs::weakly_canonical()` tests against `std::fs` 1075 | * Added simple `du` example showing the `recursive_directory_iterator` 1076 | used to add the sizes of files in a directory tree. 1077 | * Added error checking in `fs::file_time_type` test helpers 1078 | * `fs::copy()` now conforms LWG #2682, disallowing the use of 1079 | `copy_option::create_symlinks' to be used on directories 1080 | 1081 | ### [v1.1.0](https://github.com/gulrak/filesystem/releases/tag/v1.1.0) 1082 | 1083 | * Restructuring of the project directory. The header files are now using 1084 | `hpp` as extension to be marked as c++ and they where moved to 1085 | `include/ghc/` to be able to include by `` as the 1086 | former include name might have been to generic and conflict with other 1087 | files. 1088 | * Better CMake support: `ghc::filesystem` now can be used as a submodul 1089 | and added with `add_subdirectory` and will export itself as `ghc_filesystem` 1090 | target. To use it, only `target_link_libraries(your-target ghc_filesystem)` 1091 | is needed and the include directories will be set so `#include ` 1092 | will be a valid directive. 1093 | Still you can simply only add the header file to you project and include it 1094 | from there. 1095 | * Enhancement ([#10](https://github.com/gulrak/filesystem/issues/10)), 1096 | support for separation of implementation and forwarded api: Two 1097 | additional simple includes are added, that can be used to forward 1098 | `ghc::filesystem` declarations (`fs_fwd.hpp`) and to wrap the 1099 | implementation into a single cpp (`fs_impl.hpp`) 1100 | * The `std::basic_string_view` variants of the `fs::path` api are 1101 | now supported when compiling with C++17. 1102 | * Added CI integration for Travis-CI and Appveyor. 1103 | * Fixed MinGW compilation issues. 1104 | * Added long filename support for Windows. 1105 | 1106 | ### [v1.0.10](https://github.com/gulrak/filesystem/releases/tag/v1.0.10) 1107 | 1108 | * Bugfix for ([#9](https://github.com/gulrak/filesystem/issues/9)), added 1109 | missing return statement to `ghc::filesystem::path::generic_string()` 1110 | * Added checks to hopefully better compile against Android NDK. There where 1111 | no tests run yet, so feedback is needed to actually call this supported. 1112 | * `filesystem.h` was renamed `filesystem.hpp` to better reflect that it is 1113 | a c++ language header. 1114 | 1115 | ### [v1.0.8](https://github.com/gulrak/filesystem/releases/tag/v1.0.8) 1116 | 1117 | * Bugfix for ([#6](https://github.com/gulrak/filesystem/issues/6)), where 1118 | `ghc::filesystem::remove()` and `ghc::filesystem::remove_all()` both are 1119 | now able to remove a single file and both will not raise an error if the 1120 | path doesn't exist. 1121 | * Merged pull request ([#7](https://github.com/gulrak/filesystem/pull/7)), 1122 | a typo leading to setting error code instead of comparing it in 1123 | `ghc::filesystem::remove()` under Windows. 1124 | * Bugfix for (([#8](https://github.com/gulrak/filesystem/issues/8)), the 1125 | Windows version of `ghc::filesystem::directory_iterator` now releases 1126 | resources when reaching `end()` like the POSIX one does. 1127 | 1128 | 1129 | ### [v1.0.6](https://github.com/gulrak/filesystem/releases/tag/v1.0.6) 1130 | 1131 | * Bugfix for ([#4](https://github.com/gulrak/filesystem/issues/4)), missing error_code 1132 | propagation in `ghc::filesystem::copy()` and `ghc::filesystem::remove_all` fixed. 1133 | * Bugfix for ([#5](https://github.com/gulrak/filesystem/issues/5)), added missing std 1134 | namespace in `ghc::filesystem::recursive_directory_iterator::difference_type`. 1135 | 1136 | ### [v1.0.4](https://github.com/gulrak/filesystem/releases/tag/v1.0.4) 1137 | 1138 | * Bugfix for ([#3](https://github.com/gulrak/filesystem/issues/3)), fixed missing inlines 1139 | and added test to ensure including into multiple implementation files works as expected. 1140 | * Building tests with `-Wall -Wextra -Werror` and fixed resulting issues. 1141 | 1142 | ### [v1.0.2](https://github.com/gulrak/filesystem/releases/tag/v1.0.2) 1143 | 1144 | * Updated catch2 to v2.4.0. 1145 | * Refactored `fs.op.permissions` test to work with all tested `std::filesystem` 1146 | implementations (gcc, clang, msvc++). 1147 | * Added helper class `ghc::filesystem::u8arguments` as `argv` converter, to 1148 | help follow the UTF-8 path on windows. Simply instantiate it with `argc` and 1149 | `argv` and it will fetch the Unicode version of the command line and convert 1150 | it to UTF-8. The destructor reverts the change. 1151 | * Added `examples` folder with hopefully some usefull example usage. Examples are 1152 | tested (and build) with `ghc::filesystem` and C++17 `std::filesystem` when 1153 | available. 1154 | * Starting with this version, only even patch level versions will be tagged and 1155 | odd patch levels mark in-between non-stable wip states. 1156 | * Tests can now also be run against MS version of `std::filesystem` for comparison. 1157 | * Added missing `fstream` include. 1158 | * Removed non-conforming C99 `timespec`/`timeval` usage. 1159 | * Fixed some integer type mismatches that could lead to warnings. 1160 | * Fixed `chrono` conversion issues in test and example on clang 7.0.0. 1161 | 1162 | ### [v1.0.1](https://github.com/gulrak/filesystem/releases/tag/v1.0.1) 1163 | 1164 | * Bugfix: `ghc::filesystem::canonical` now sees empty path as non-existant and reports 1165 | an error. Due to this `ghc::filesystem::weakly_canonical` now returns relative 1166 | paths for non-existant argument paths. ([#1](https://github.com/gulrak/filesystem/issues/1)) 1167 | * Bugfix: `ghc::filesystem::remove_all` now also counts directories removed ([#2](https://github.com/gulrak/filesystem/issues/2)) 1168 | * Bugfix: `recursive_directory_iterator` tests didn't respect equality domain issues 1169 | and dereferencapable constraints, leading to fails on `std::filesystem` tests. 1170 | * Bugfix: Some `noexcept` tagged methods and functions could indirectly throw exceptions 1171 | due to UFT-8 decoding issues. 1172 | * `std_filesystem_test` is now also generated if LLVM/clang 7.0.0 is found. 1173 | 1174 | 1175 | ### [v1.0.0](https://github.com/gulrak/filesystem/releases/tag/v1.0.0) 1176 | 1177 | This was the first public release version. It implements the full range of 1178 | C++17 `std::filesystem`, as far as possible without other C++17 dependencies. 1179 | 1180 | -------------------------------------------------------------------------------- /cmake/GhcHelper.cmake: -------------------------------------------------------------------------------- 1 | macro(AddExecutableWithStdFS targetName) 2 | if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)) 3 | if(APPLE) 4 | include_directories(/usr/local/opt/llvm/include) 5 | link_directories(/usr/local/opt/llvm/lib) 6 | endif() 7 | add_executable(${targetName} ${ARGN}) 8 | set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17) 9 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) 10 | if(APPLE) 11 | target_link_libraries(${targetName} -lc++fs) 12 | else() 13 | target_compile_options(${targetName} PRIVATE "-stdlib=libc++") 14 | target_link_libraries(${targetName} -stdlib=libc++ -lc++fs $<$:rt>) 15 | endif() 16 | else() 17 | if(NOT APPLE) 18 | target_compile_options(${targetName} PRIVATE "-stdlib=libc++") 19 | target_link_libraries(${targetName} -stdlib=libc++) 20 | endif() 21 | endif() 22 | if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)") 23 | target_link_libraries(filesystem_test xnet) 24 | endif() 25 | if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku") 26 | target_link_libraries(filesystem_test network) 27 | endif() 28 | target_compile_definitions(${targetName} PRIVATE USE_STD_FS) 29 | endif() 30 | 31 | if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0)) 32 | add_executable(${targetName} ${ARGN}) 33 | set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17) 34 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) 35 | target_link_libraries(${targetName} -lstdc++fs) 36 | endif() 37 | if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)") 38 | target_link_libraries(${targetName} xnet) 39 | endif() 40 | if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku") 41 | target_link_libraries(${targetName} network) 42 | endif() 43 | target_compile_options(${targetName} PRIVATE $<$:-Wa,-mbig-obj>) 44 | target_compile_definitions(${targetName} PRIVATE USE_STD_FS) 45 | endif() 46 | 47 | if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15)) 48 | add_executable(${targetName} ${ARGN}) 49 | set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17) 50 | set_property(TARGET ${targetName} PROPERTY CXX_STANDARD_REQUIRED ON) 51 | target_compile_options(${targetName} PRIVATE "/Zc:__cplusplus") 52 | target_compile_definitions(${targetName} PRIVATE USE_STD_FS _CRT_SECURE_NO_WARNINGS) 53 | endif() 54 | 55 | endmacro() 56 | 57 | macro(AddTestExecutableWithStdCpp cppStd) 58 | add_executable(filesystem_test_cpp${cppStd} ${ARGN}) 59 | set_property(TARGET filesystem_test_cpp${cppStd} PROPERTY CXX_STANDARD ${cppStd}) 60 | target_link_libraries(filesystem_test_cpp${cppStd} ghc_filesystem) 61 | if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)") 62 | target_link_libraries(filesystem_test_cpp${cppStd} xnet) 63 | endif() 64 | if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku") 65 | target_link_libraries(filesystem_test_cpp${cppStd} network) 66 | endif() 67 | target_compile_options(filesystem_test_cpp${cppStd} PRIVATE 68 | $<$:-s DISABLE_EXCEPTION_CATCHING=0> 69 | $<$,$>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror -Wno-error=deprecated-declarations> 70 | $<$:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror -Wno-error=deprecated-declarations> 71 | $<$:/WX /wd4996> 72 | $<$:-Wa,-mbig-obj> 73 | $<$:--coverage>) 74 | if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) 75 | target_compile_definitions(filesystem_test_cpp${cppStd} PRIVATE _CRT_SECURE_NO_WARNINGS) 76 | endif() 77 | if(EMSCRIPTEN) 78 | set_target_properties(filesystem_test_cpp${cppStd} PROPERTIES LINK_FLAGS "-g4 -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1") 79 | endif() 80 | ParseAndAddCatchTests(filesystem_test_cpp${cppStd}) 81 | endmacro() 82 | -------------------------------------------------------------------------------- /cmake/config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | # import targets 4 | include("${CMAKE_CURRENT_LIST_DIR}/ghc_filesystem-targets.cmake") 5 | 6 | check_required_components(ghcfilesystem) -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(fs_dir dir.cpp) 3 | target_link_libraries(fs_dir ghc_filesystem) 4 | if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) 5 | target_compile_definitions(fs_dir PRIVATE _CRT_SECURE_NO_WARNINGS) 6 | endif() 7 | AddExecutableWithStdFS(std_fs_dir dir.cpp) 8 | 9 | add_executable(fs_du du.cpp) 10 | target_link_libraries(fs_du ghc_filesystem) 11 | AddExecutableWithStdFS(std_fs_du du.cpp) 12 | 13 | if(EXISTS "${PROJECT_SOURCE_DIR}/examples/benchmark.cpp") 14 | add_executable(fs_benchmark benchmark.cpp) 15 | set_property(TARGET fs_benchmark PROPERTY CXX_STANDARD 17) 16 | target_link_libraries(fs_benchmark ghc_filesystem) 17 | endif() -------------------------------------------------------------------------------- /examples/dir.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include) 7 | #if __has_include() 8 | #define GHC_USE_STD_FS 9 | #include 10 | namespace fs = std::filesystem; 11 | #endif 12 | #endif 13 | #ifndef GHC_USE_STD_FS 14 | #include 15 | namespace fs = ghc::filesystem; 16 | #endif 17 | 18 | template 19 | std::time_t to_time_t(TP tp) 20 | { 21 | // Based on trick from: Nico Josuttis, C++17 - The Complete Guide 22 | std::chrono::system_clock::duration dt = std::chrono::duration_cast(tp - TP::clock::now()); 23 | return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + dt); 24 | } 25 | 26 | static std::string perm_to_str(fs::perms prms) 27 | { 28 | std::string result; 29 | result.reserve(9); 30 | for (int i = 0; i < 9; ++i) { 31 | result = ((static_cast(prms) & (1 << i)) ? "xwrxwrxwr"[i] : '-') + result; 32 | } 33 | return result; 34 | } 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | #ifdef GHC_FILESYSTEM_VERSION 39 | fs::u8arguments u8guard(argc, argv); 40 | if (!u8guard.valid()) { 41 | std::cerr << "Invalid character encoding, UTF-8 based encoding needed." << std::endl; 42 | std::exit(EXIT_FAILURE); 43 | } 44 | #endif 45 | if (argc > 2) { 46 | std::cerr << "USAGE: dir " << std::endl; 47 | exit(1); 48 | } 49 | fs::path dir{"."}; 50 | if (argc == 2) { 51 | dir = fs::u8path(argv[1]); 52 | } 53 | for (auto de : fs::directory_iterator(dir)) { 54 | auto ft = to_time_t(de.last_write_time()); 55 | auto ftm = *std::localtime(&ft); 56 | std::cout << (de.is_directory() ? "d" : "-") << perm_to_str(de.symlink_status().permissions()) << " " << std::setw(8) << (de.is_directory() ? "-" : std::to_string(de.file_size())) << " " << std::put_time(&ftm, "%Y-%m-%d %H:%M:%S") << " " 57 | << de.path().filename().string() << std::endl; 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /examples/du.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include) 6 | #if __has_include() 7 | #define GHC_USE_STD_FS 8 | #include 9 | namespace fs = std::filesystem; 10 | #endif 11 | #endif 12 | #ifndef GHC_USE_STD_FS 13 | #include 14 | namespace fs = ghc::filesystem; 15 | #endif 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | #ifdef GHC_FILESYSTEM_VERSION 20 | fs::u8arguments u8guard(argc, argv); 21 | if(!u8guard.valid()) { 22 | std::cerr << "Invalid character encoding, UTF-8 based encoding needed." << std::endl; 23 | std::exit(EXIT_FAILURE); 24 | } 25 | #endif 26 | if(argc > 2) { 27 | std::cerr << "USAGE: du " << std::endl; 28 | exit(1); 29 | } 30 | fs::path dir{"."}; 31 | if(argc == 2) { 32 | dir = fs::u8path(argv[1]); 33 | } 34 | 35 | uint64_t totalSize = 0; 36 | int totalDirs = 0; 37 | int totalFiles = 0; 38 | int maxDepth = 0; 39 | 40 | try { 41 | auto rdi = fs::recursive_directory_iterator(dir); 42 | for(auto de : rdi) { 43 | if(rdi.depth() > maxDepth) { 44 | maxDepth = rdi.depth(); 45 | } 46 | if(de.is_regular_file()) { 47 | totalSize += de.file_size(); 48 | ++totalFiles; 49 | } 50 | else if(de.is_directory()) { 51 | ++totalDirs; 52 | } 53 | } 54 | } 55 | catch(fs::filesystem_error fe) { 56 | std::cerr << "Error: " << fe.what() << std::endl; 57 | exit(1); 58 | } 59 | std::cout << totalSize << " bytes in " << totalFiles << " files and " << totalDirs << " directories, maximum depth: " << maxDepth << std::endl; 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /include/ghc/fs_fwd.hpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 4 | // 5 | //--------------------------------------------------------------------------------------- 6 | // 7 | // Copyright (c) 2018, Steffen Schümann 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | //--------------------------------------------------------------------------------------- 28 | // fs_fwd.hpp - The forwarding header for the header/implementation separated usage of 29 | // ghc::filesystem. 30 | // This file can be include at any place, where ghc::filesystem api is needed while 31 | // not bleeding implementation details (e.g. system includes) into the global namespace, 32 | // as long as one cpp includes fs_impl.hpp to deliver the matching implementations. 33 | //--------------------------------------------------------------------------------------- 34 | #ifndef GHC_FILESYSTEM_FWD_H 35 | #define GHC_FILESYSTEM_FWD_H 36 | #define GHC_FILESYSTEM_FWD 37 | #include "filesystem.hpp" 38 | #endif // GHC_FILESYSTEM_FWD_H 39 | -------------------------------------------------------------------------------- /include/ghc/fs_impl.hpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 4 | // 5 | //--------------------------------------------------------------------------------------- 6 | // 7 | // Copyright (c) 2018, Steffen Schümann 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | //--------------------------------------------------------------------------------------- 28 | // fs_impl.hpp - The implementation header for the header/implementation separated usage of 29 | // ghc::filesystem. 30 | // This file can be used to hide the implementation of ghc::filesystem into a single cpp. 31 | // The cpp has to include this before including fs_fwd.hpp directly or via a different 32 | // header to work. 33 | //--------------------------------------------------------------------------------------- 34 | #define GHC_FILESYSTEM_IMPLEMENTATION 35 | #include "filesystem.hpp" 36 | -------------------------------------------------------------------------------- /include/ghc/fs_std.hpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 4 | // 5 | //--------------------------------------------------------------------------------------- 6 | // 7 | // Copyright (c) 2018, Steffen Schümann 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | //--------------------------------------------------------------------------------------- 28 | // fs_std.hpp - The dynamic switching header that includes std::filesystem if detected 29 | // or ghc::filesystem if not, and makes the resulting API available in the 30 | // namespace fs. 31 | //--------------------------------------------------------------------------------------- 32 | #ifndef GHC_FILESYSTEM_STD_H 33 | #define GHC_FILESYSTEM_STD_H 34 | 35 | #if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) 36 | // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus 37 | // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ 38 | #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html 39 | #define GHC_USE_STD_FS 40 | 41 | // Old Apple OSs don't support std::filesystem, though the header is available at compile 42 | // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, 43 | // and watchOS 6.0. 44 | #ifdef __APPLE__ 45 | #include 46 | // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS 47 | // released after std::filesystem, where std::filesystem is always available. 48 | // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) 49 | #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ 50 | || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ 51 | || defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ 52 | || defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 53 | #undef GHC_USE_STD_FS 54 | #endif 55 | #endif 56 | #endif 57 | #endif 58 | 59 | #ifdef GHC_USE_STD_FS 60 | #include 61 | namespace fs { 62 | using namespace std::filesystem; 63 | using ifstream = std::ifstream; 64 | using ofstream = std::ofstream; 65 | using fstream = std::fstream; 66 | } 67 | #else 68 | #include "filesystem.hpp" 69 | namespace fs { 70 | using namespace ghc::filesystem; 71 | using ifstream = ghc::filesystem::ifstream; 72 | using ofstream = ghc::filesystem::ofstream; 73 | using fstream = ghc::filesystem::fstream; 74 | } 75 | #endif 76 | 77 | #endif // GHC_FILESYSTEM_STD_H 78 | -------------------------------------------------------------------------------- /include/ghc/fs_std_fwd.hpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 4 | // 5 | //--------------------------------------------------------------------------------------- 6 | // 7 | // Copyright (c) 2018, Steffen Schümann 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | //--------------------------------------------------------------------------------------- 28 | // fs_std_fwd.hpp - The forwarding header for the header/implementation separated usage of 29 | // ghc::filesystem that uses std::filesystem if it detects it. 30 | // This file can be include at any place, where fs::filesystem api is needed while 31 | // not bleeding implementation details (e.g. system includes) into the global namespace, 32 | // as long as one cpp includes fs_std_impl.hpp to deliver the matching implementations. 33 | //--------------------------------------------------------------------------------------- 34 | #ifndef GHC_FILESYSTEM_STD_FWD_H 35 | #define GHC_FILESYSTEM_STD_FWD_H 36 | 37 | #if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) 38 | // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus 39 | // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ 40 | #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html 41 | #define GHC_USE_STD_FS 42 | 43 | // Old Apple OSs don't support std::filesystem, though the header is available at compile 44 | // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, 45 | // and watchOS 6.0. 46 | #ifdef __APPLE__ 47 | #include 48 | // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS 49 | // released after std::filesystem, where std::filesystem is always available. 50 | // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) 51 | #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ 52 | || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ 53 | || defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ 54 | || defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 55 | #undef GHC_USE_STD_FS 56 | #endif 57 | #endif 58 | #endif 59 | #endif 60 | 61 | #ifdef GHC_USE_STD_FS 62 | #include 63 | namespace fs { 64 | using namespace std::filesystem; 65 | using ifstream = std::ifstream; 66 | using ofstream = std::ofstream; 67 | using fstream = std::fstream; 68 | } 69 | #else 70 | #include "fs_fwd.hpp" 71 | namespace fs { 72 | using namespace ghc::filesystem; 73 | using ifstream = ghc::filesystem::ifstream; 74 | using ofstream = ghc::filesystem::ofstream; 75 | using fstream = ghc::filesystem::fstream; 76 | } 77 | #endif 78 | 79 | #endif // GHC_FILESYSTEM_STD_FWD_H 80 | -------------------------------------------------------------------------------- /include/ghc/fs_std_impl.hpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 4 | // 5 | //--------------------------------------------------------------------------------------- 6 | // 7 | // Copyright (c) 2018, Steffen Schümann 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | //--------------------------------------------------------------------------------------- 28 | // fs_std_impl.hpp - The implementation header for the header/implementation separated usage of 29 | // ghc::filesystem that does nothing if std::filesystem is detected. 30 | // This file can be used to hide the implementation of ghc::filesystem into a single cpp. 31 | // The cpp has to include this before including fs_std_fwd.hpp directly or via a different 32 | // header to work. 33 | //--------------------------------------------------------------------------------------- 34 | #if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) 35 | // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus 36 | // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ 37 | #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html 38 | #define GHC_USE_STD_FS 39 | 40 | // Old Apple OSs don't support std::filesystem, though the header is available at compile 41 | // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, 42 | // and watchOS 6.0. 43 | #ifdef __APPLE__ 44 | #include 45 | // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS 46 | // released after std::filesystem, where std::filesystem is always available. 47 | // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) 48 | #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ 49 | || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ 50 | || defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ 51 | || defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 52 | #undef GHC_USE_STD_FS 53 | #endif 54 | #endif 55 | #endif 56 | #endif 57 | 58 | #ifndef GHC_USE_STD_FS 59 | #include "fs_impl.hpp" 60 | #endif 61 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") 3 | set(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS ON) 4 | include(ParseAndAddCatchTests) 5 | 6 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND UNIX AND NOT APPLE AND NOT BSD) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") 8 | set(CMAKE_EXE_LINKER_FLAGS "-lc++abi") 9 | endif() 10 | 11 | function(SetTestCompileOptions target_name) 12 | target_compile_options(${target_name} PRIVATE 13 | $<$:-s DISABLE_EXCEPTION_CATCHING=0> 14 | $<$,$>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror -Wno-deprecated-declarations> 15 | $<$:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror -Wno-deprecated-declarations> 16 | $<$:/WX /wd4996> 17 | $<$:-Wa,-mbig-obj>) 18 | endfunction() 19 | 20 | if(GHC_COVERAGE) 21 | message("Generating test runner for coverage run...") 22 | set(CMAKE_EXE_LINKER_FLAGS "${CMCMAKE_EXE_LINKER_FLAGS} --coverage") 23 | add_executable(filesystem_test filesystem_test.cpp catch.hpp) 24 | if(MINGW) 25 | target_compile_options(filesystem_test PUBLIC --coverage "-Wa,-mbig-obj") 26 | else() 27 | target_compile_options(filesystem_test PUBLIC --coverage) 28 | endif() 29 | target_link_libraries(filesystem_test PUBLIC ghc_filesystem --coverage) 30 | if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)") 31 | target_link_libraries(filesystem_test PUBLIC xnet) 32 | endif() 33 | if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku") 34 | target_link_libraries(filesystem_test PUBLIC network) 35 | endif() 36 | if("cxx_std_17" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES) 37 | AddTestExecutableWithStdCpp(17 filesystem_test.cpp catch.hpp) 38 | endif() 39 | if("cxx_std_20" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES) 40 | AddTestExecutableWithStdCpp(20 filesystem_test.cpp catch.hpp) 41 | endif() 42 | else() 43 | message("Generating test runner for normal test...") 44 | add_executable(filesystem_test filesystem_test.cpp catch.hpp) 45 | target_link_libraries(filesystem_test ghc_filesystem) 46 | if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)") 47 | target_link_libraries(filesystem_test xnet) 48 | endif() 49 | if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku") 50 | target_link_libraries(filesystem_test network) 51 | endif() 52 | SetTestCompileOptions(filesystem_test) 53 | if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) 54 | target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX) 55 | endif() 56 | if(EMSCRIPTEN) 57 | set_target_properties(filesystem_test PROPERTIES LINK_FLAGS "-g4 -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1") 58 | endif() 59 | ParseAndAddCatchTests(filesystem_test) 60 | if(GHC_FILESYSTEM_BUILD_STD_TESTING) 61 | AddExecutableWithStdFS(std_filesystem_test filesystem_test.cpp catch.hpp) 62 | endif() 63 | if(WIN32) 64 | add_executable(filesystem_test_char filesystem_test.cpp catch.hpp) 65 | target_link_libraries(filesystem_test_char ghc_filesystem) 66 | SetTestCompileOptions(filesystem_test_char) 67 | if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) 68 | target_compile_definitions(filesystem_test_char PRIVATE _CRT_SECURE_NO_WARNINGS GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE) 69 | else() 70 | target_compile_definitions(filesystem_test_char PRIVATE GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE) 71 | endif() 72 | ParseAndAddCatchTests(filesystem_test_char) 73 | endif() 74 | if("cxx_std_17" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES) 75 | AddTestExecutableWithStdCpp(17 filesystem_test.cpp catch.hpp) 76 | endif() 77 | if("cxx_std_20" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES) 78 | AddTestExecutableWithStdCpp(20 filesystem_test.cpp catch.hpp) 79 | endif() 80 | endif() 81 | 82 | add_executable(multifile_test multi1.cpp multi2.cpp catch.hpp) 83 | target_link_libraries(multifile_test ghc_filesystem) 84 | add_test(multifile_test multifile_test) 85 | 86 | add_executable(fwd_impl_test fwd_test.cpp impl_test.cpp) 87 | target_link_libraries(fwd_impl_test ghc_filesystem) 88 | if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)") 89 | target_link_libraries(fwd_impl_test xnet) 90 | endif() 91 | if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku") 92 | target_link_libraries(fwd_impl_test network) 93 | endif() 94 | SetTestCompileOptions(fwd_impl_test) 95 | if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) 96 | target_compile_definitions(fwd_impl_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX) 97 | endif() 98 | add_test(fwd_impl_test fwd_impl_test) 99 | 100 | add_executable(exception exception.cpp) 101 | if(NOT MSVC) 102 | target_compile_options(exception PRIVATE -fno-exceptions) 103 | endif() 104 | target_include_directories(exception PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) 105 | SetTestCompileOptions(exception) 106 | -------------------------------------------------------------------------------- /test/cmake/ParseAndAddCatchTests.cmake: -------------------------------------------------------------------------------- 1 | #==================================================================================================# 2 | # supported macros # 3 | # - TEST_CASE, # 4 | # - SCENARIO, # 5 | # - TEST_CASE_METHOD, # 6 | # - CATCH_TEST_CASE, # 7 | # - CATCH_SCENARIO, # 8 | # - CATCH_TEST_CASE_METHOD. # 9 | # # 10 | # Usage # 11 | # 1. make sure this module is in the path or add this otherwise: # 12 | # set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") # 13 | # 2. make sure that you've enabled testing option for the project by the call: # 14 | # enable_testing() # 15 | # 3. add the lines to the script for testing target (sample CMakeLists.txt): # 16 | # project(testing_target) # 17 | # set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") # 18 | # enable_testing() # 19 | # # 20 | # find_path(CATCH_INCLUDE_DIR "catch.hpp") # 21 | # include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) # 22 | # # 23 | # file(GLOB SOURCE_FILES "*.cpp") # 24 | # add_executable(${PROJECT_NAME} ${SOURCE_FILES}) # 25 | # # 26 | # include(ParseAndAddCatchTests) # 27 | # ParseAndAddCatchTests(${PROJECT_NAME}) # 28 | # # 29 | # The following variables affect the behavior of the script: # 30 | # # 31 | # PARSE_CATCH_TESTS_VERBOSE (Default OFF) # 32 | # -- enables debug messages # 33 | # PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) # 34 | # -- excludes tests marked with [!hide], [.] or [.foo] tags # 35 | # PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) # 36 | # -- adds fixture class name to the test name # 37 | # PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) # 38 | # -- adds cmake target name to the test name # 39 | # PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) # 40 | # -- causes CMake to rerun when file with tests changes so that new tests will be discovered # 41 | # # 42 | # One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way # 43 | # a test should be run. For instance to use test MPI, one can write # 44 | # set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) # 45 | # just before calling this ParseAndAddCatchTests function # 46 | # # 47 | # The AdditionalCatchParameters optional variable can be used to pass extra argument to the test # 48 | # command. For example, to include successful tests in the output, one can write # 49 | # set(AdditionalCatchParameters --success) # 50 | # # 51 | # After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source # 52 | # file in the target is set, and contains the list of the tests extracted from that target, or # 53 | # from that file. This is useful, for example to add further labels or properties to the tests. # 54 | # # 55 | #==================================================================================================# 56 | 57 | if (CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8) 58 | message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer") 59 | endif() 60 | 61 | option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF) 62 | option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF) 63 | option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON) 64 | option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON) 65 | option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF) 66 | 67 | function(ParseAndAddCatchTests_PrintDebugMessage) 68 | if(PARSE_CATCH_TESTS_VERBOSE) 69 | message(STATUS "ParseAndAddCatchTests: ${ARGV}") 70 | endif() 71 | endfunction() 72 | 73 | # This removes the contents between 74 | # - block comments (i.e. /* ... */) 75 | # - full line comments (i.e. // ... ) 76 | # contents have been read into '${CppCode}'. 77 | # !keep partial line comments 78 | function(ParseAndAddCatchTests_RemoveComments CppCode) 79 | string(ASCII 2 CMakeBeginBlockComment) 80 | string(ASCII 3 CMakeEndBlockComment) 81 | string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}") 82 | string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}") 83 | string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}") 84 | string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}") 85 | 86 | set(${CppCode} "${${CppCode}}" PARENT_SCOPE) 87 | endfunction() 88 | 89 | # Worker function 90 | function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget) 91 | # If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file. 92 | if(SourceFile MATCHES "\\\$") 93 | ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.") 94 | return() 95 | endif() 96 | # According to CMake docs EXISTS behavior is well-defined only for full paths. 97 | get_filename_component(SourceFile ${SourceFile} ABSOLUTE) 98 | if(NOT EXISTS ${SourceFile}) 99 | message(WARNING "Cannot find source file: ${SourceFile}") 100 | return() 101 | endif() 102 | ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}") 103 | file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME) 104 | 105 | # Remove block and fullline comments 106 | ParseAndAddCatchTests_RemoveComments(Contents) 107 | 108 | # Find definition of test names 109 | string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}") 110 | 111 | if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests) 112 | ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property") 113 | set_property( 114 | DIRECTORY 115 | APPEND 116 | PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile} 117 | ) 118 | endif() 119 | 120 | foreach(TestName ${Tests}) 121 | # Strip newlines 122 | string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}") 123 | 124 | # Get test type and fixture if applicable 125 | string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}") 126 | string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}") 127 | string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}") 128 | 129 | # Get string parts of test definition 130 | string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}") 131 | 132 | # Strip wrapping quotation marks 133 | string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}") 134 | string(REPLACE "\";\"" ";" TestStrings "${TestStrings}") 135 | 136 | # Validate that a test name and tags have been provided 137 | list(LENGTH TestStrings TestStringsLength) 138 | if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1) 139 | message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}") 140 | endif() 141 | 142 | # Assign name and tags 143 | list(GET TestStrings 0 Name) 144 | if("${TestType}" STREQUAL "SCENARIO") 145 | set(Name "Scenario: ${Name}") 146 | endif() 147 | if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture ) 148 | set(CTestName "${TestFixture}:${Name}") 149 | else() 150 | set(CTestName "${Name}") 151 | endif() 152 | if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME) 153 | set(CTestName "${TestTarget}:${CTestName}") 154 | endif() 155 | # add target to labels to enable running all tests added from this target 156 | set(Labels ${TestTarget}) 157 | if(TestStringsLength EQUAL 2) 158 | list(GET TestStrings 1 Tags) 159 | string(TOLOWER "${Tags}" Tags) 160 | # remove target from labels if the test is hidden 161 | if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*") 162 | list(REMOVE_ITEM Labels ${TestTarget}) 163 | endif() 164 | string(REPLACE "]" ";" Tags "${Tags}") 165 | string(REPLACE "[" "" Tags "${Tags}") 166 | else() 167 | # unset tags variable from previous loop 168 | unset(Tags) 169 | endif() 170 | 171 | list(APPEND Labels ${Tags}) 172 | 173 | set(HiddenTagFound OFF) 174 | foreach(label ${Labels}) 175 | string(REGEX MATCH "^!hide|^\\." result ${label}) 176 | if(result) 177 | set(HiddenTagFound ON) 178 | break() 179 | endif(result) 180 | endforeach(label) 181 | if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9") 182 | ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label") 183 | else() 184 | ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"") 185 | if(Labels) 186 | ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}") 187 | endif() 188 | 189 | # Escape commas in the test spec 190 | string(REPLACE "," "\\," Name ${Name}) 191 | 192 | # Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were neccessary, 193 | # only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1 194 | if(NOT ${CMAKE_VERSION} VERSION_EQUAL "3.18") 195 | set(CTestName "\"${CTestName}\"") 196 | endif() 197 | # Add the test and set its properties 198 | add_test(NAME "${CTestName}" COMMAND ${OptionalCatchTestLauncher} $ ${Name} ${AdditionalCatchParameters}) 199 | # Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead 200 | if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8") 201 | ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property") 202 | set_tests_properties("${CTestName}" PROPERTIES DISABLED ON) 203 | else() 204 | set_tests_properties("${CTestName}" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran" 205 | LABELS "${Labels}") 206 | endif() 207 | set_property( 208 | TARGET ${TestTarget} 209 | APPEND 210 | PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}") 211 | set_property( 212 | SOURCE ${SourceFile} 213 | APPEND 214 | PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}") 215 | endif() 216 | 217 | 218 | endforeach() 219 | endfunction() 220 | 221 | # entry point 222 | function(ParseAndAddCatchTests TestTarget) 223 | ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}") 224 | get_target_property(SourceFiles ${TestTarget} SOURCES) 225 | ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}") 226 | foreach(SourceFile ${SourceFiles}) 227 | ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget}) 228 | endforeach() 229 | ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}") 230 | endfunction() 231 | -------------------------------------------------------------------------------- /test/exception.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /test/fwd_test.cpp: -------------------------------------------------------------------------------- 1 | // This test file is part of the fwd_test.cpp/impl_test.cpp pair 2 | // and used to test the new optional two-part usage of ghc::filesystem 3 | // where exactly one cpp includes fs_impl.hpp and all others use 4 | // fs_fwd.hpp (to test this with maximum functionality, the unit tests 5 | // are included here, signaling they should only include the fs_fwd.hpp) 6 | #define GHC_FILESYSTEM_FWD_TEST 7 | #include "filesystem_test.cpp" 8 | -------------------------------------------------------------------------------- /test/impl_test.cpp: -------------------------------------------------------------------------------- 1 | // This test file is part of the fwd_test.cpp/impl_test.cpp pair 2 | // and used to test the new optional two-part usage of ghc::filesystem 3 | // where exactly one cpp includes fs_impl.hpp and all others use 4 | // fs_fwd.hpp (to test this with maximum functionality, the unit tests 5 | // are included here, signaling they should only include the fs_fwd.hpp) 6 | #include 7 | #define CATCH_CONFIG_MAIN 8 | #include "catch.hpp" 9 | -------------------------------------------------------------------------------- /test/multi1.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2018, Steffen Schümann 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // 23 | //--------------------------------------------------------------------------------------- 24 | #define CATCH_CONFIG_MAIN 25 | #include "catch.hpp" 26 | 27 | #include 28 | namespace fs = ghc::filesystem; 29 | 30 | // This test and the one in multi2.cpp doesn't actually test relevant functionality, 31 | // it is just used to check that it is possible to include filesystem.h in multiple 32 | // source files. 33 | TEST_CASE("Multifile-test 1", "[multi]") 34 | { 35 | CHECK("/usr/local/bin" == fs::path("/usr/local/bin").generic_string()); 36 | std::string str = "/usr/local/bin"; 37 | std::u16string u16str = u"/usr/local/bin"; 38 | std::u32string u32str = U"/usr/local/bin"; 39 | CHECK(str == fs::path(str.begin(), str.end())); 40 | CHECK(str == fs::path(u16str.begin(), u16str.end())); 41 | CHECK(str == fs::path(u32str.begin(), u32str.end())); 42 | } 43 | -------------------------------------------------------------------------------- /test/multi2.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2018, Steffen Schümann 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | // 23 | //--------------------------------------------------------------------------------------- 24 | #include "catch.hpp" 25 | #include 26 | namespace fs = ghc::filesystem; 27 | 28 | // This test and the one in multi1.cpp doesn't actualy test relevant functionality, 29 | // it is just used to check that it is possible to include filesystem.h in multiple 30 | // source files. 31 | TEST_CASE("Multifile-test 2", "[multi]") 32 | { 33 | CHECK("/usr/local/bin" == fs::path("/usr/local/bin").generic_string()); 34 | std::string str = "/usr/local/bin"; 35 | std::u16string u16str = u"/usr/local/bin"; 36 | std::u32string u32str = U"/usr/local/bin"; 37 | CHECK(str == fs::path(str.begin(), str.end())); 38 | CHECK(str == fs::path(u16str.begin(), u16str.end())); 39 | CHECK(str == fs::path(u32str.begin(), u32str.end())); 40 | } 41 | --------------------------------------------------------------------------------