From e83cd7c44916105034f2d539a5e55a6c6f178a7f Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Thu, 4 Apr 2024 18:34:10 -0700 Subject: [PATCH] build!: Move to C++17 minimum (#4199) These are build-breaking changes that impose a variety of new minimum dependencies for the toolchain. C++17 is the new minimum. All hail C++17. Bump minimum compiler versions to the respective releases of each one that is requred to fully support C++17 for us. This means new minimum changes of gcc 6.1 -> 9.3, clang 3.4 -> 5.0, icc 17 -> 19, and MSVS v19.14 or higher now. Remove CI tests for too-old platforms, and adjust some others that needed particular components upgraded. We now will no longer attempt to test on "VFX Platform 2019" or 2020. The 2021 platforms are the earliest we claim to support (reflecting VFXP's guidance about trying to support up to 3 years back). By removing the old test cases, we're also removing the last platforms that test Python 2.7. So while this PR isn't the one that officially removes the last vestiges of Python 2, it does mean that once this is merged, we will no longer be testing less than Python 3.7. (A separate PR removing all Python 2 support will follow and presumably be merged around the same time.) With C++17 min, remove traces of boost::filesystem. We can rely on std::filesystem now. Clean up pre-C++17 macros in platform.h Needless to say, this will not be backported to any release branches, which guarantee that they will never raise the minimum supported versions of any dependencies. This is just for future OIIO. I won't merge this until after April 1, at which point I will also tag the last spot in master that is known to work with C++14/gcc6. Signed-off-by: Larry Gritz --- .github/workflows/ci.yml | 63 +++++--------------- INSTALL.md | 9 ++- Makefile | 2 +- src/build-scripts/ci-startup.bash | 2 +- src/build-scripts/gh-installdeps.bash | 10 +--- src/cmake/compiler.cmake | 27 +-------- src/cmake/externalpackages.cmake | 7 +-- src/doc/Doxyfile | 1 - src/include/OpenImageIO/detail/farmhash.h | 10 +--- src/include/OpenImageIO/oiioversion.h.in | 2 +- src/include/OpenImageIO/platform.h | 55 +++++------------ src/include/OpenImageIO/string_view.h | 24 ++++---- src/include/OpenImageIO/ustring.h | 4 +- src/libutil/filesystem.cpp | 69 ++++------------------ src/libutil/filesystem_test.cpp | 3 + src/oiiotool/printinfo.cpp | 2 +- testsuite/cmake-consumer/CMakeLists.txt | 4 +- testsuite/docs-examples-cpp/CMakeLists.txt | 4 +- 18 files changed, 78 insertions(+), 220 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 837034aa65..2a06d15184 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,29 +34,6 @@ jobs: fail-fast: false matrix: include: - - desc: gcc6/C++14 py2.7 boost1.66 exr2.4 ocio1.1 - nametag: linux-vfx2019 - runner: ubuntu-latest - container: aswf/ci-osl:2019 - vfxyear: 2019 - cxx_std: 14 - openexr_ver: v2.4.3 - python_ver: 2.7 - simd: sse4.2 - fmt_ver: 7.0.1 - pybind11_ver: v2.4.2 - setenvs: export PUGIXML_VERSION=v1.9 CMAKE_VERSION=3.15.5 - - desc: gcc6/C++14 py3.7 boost1.70 exr2.4 ocio1.1 - nametag: linux-vfx2020 - runner: ubuntu-latest - container: aswf/ci-osl:2020 - vfxyear: 2020 - cxx_std: 14 - python_ver: 3.7 - simd: avx - fmt_ver: 7.0.1 - pybind11_ver: v2.5.0 - setenvs: export PUGIXML_VERSION=v1.9 WEBP_VERSION=v1.1.0 - desc: gcc9/C++17 py3.7 boost1.73 exr2.5 ocio2.0 nametag: linux-vfx2021 runner: ubuntu-latest @@ -68,14 +45,14 @@ jobs: fmt_ver: 7.1.0 pybind11_ver: v2.7.0 setenvs: export PUGIXML_VERSION=v1.9 WEBP_VERSION=v1.1.0 - - desc: clang10/C++14 avx2 exr2.5 ocio2.0 + - desc: clang10/C++17 avx2 exr2.5 ocio2.0 nametag: linux-clang10-cpp14 runner: ubuntu-latest container: aswf/ci-osl:2021-clang10 vfxyear: 2021 cc_compiler: clang cxx_compiler: clang++ - cxx_std: 14 + cxx_std: 17 pybind11_ver: v2.6.2 python_ver: 3.7 simd: "avx2,f16c" @@ -163,18 +140,18 @@ jobs: simd: "avx2,f16c" fmt_ver: 10.1.1 pybind11_ver: v2.10.0 - - desc: oldest/hobbled gcc6.3/C++14 py2.7 boost-1.66 exr-2.4 no-sse no-ocio + - desc: oldest/hobbled gcc9.3/C++17 py3.7 boost-1.66 exr-2.4 no-sse no-ocio # Oldest versions of the dependencies that we can muster, and various # things disabled (no SSE, OCIO, or OpenCV, don't embed plugins). nametag: linux-oldest runner: ubuntu-latest - container: aswf/ci-osl:2019 - vfxyear: 2019 - cxx_std: 14 + container: aswf/ci-osl:2021 + vfxyear: 2021 + cxx_std: 17 fmt_ver: 7.0.1 openexr_ver: v2.4.0 pybind11_ver: v2.4.2 - python_ver: 2.7 + python_ver: 3.7 simd: 0 setenvs: export EMBEDPLUGINS=0 CMAKE_VERSION=3.15.5 @@ -352,13 +329,13 @@ jobs: OPENCOLORIO_VERSION=v2.1.2 USE_OPENVDB=0 # The installed OpenVDB has a TLS conflict with Python 3.8 - - desc: debug gcc7/C++14, sse4.2, exr2.4 - nametag: linux-gcc7-cpp14-debug + - desc: debug gcc9/C++17, sse4.2, exr2.4 + nametag: linux-gcc9-cpp17-debug runner: ubuntu-20.04 container: image: ubuntu-18.04 - cxx_compiler: g++-7 - cxx_std: 14 + cxx_compiler: g++-9 + cxx_std: 17 python_ver: 2.7 simd: sse4.2 openexr_ver: v2.4.3 @@ -367,25 +344,13 @@ jobs: PUGIXML_VERSION=v1.9 CTEST_TEST_TIMEOUT=1200 - - desc: gcc8 C++17 avx exr2.5 - nametag: linux-gcc8 - runner: ubuntu-20.04 - container: - image: ubuntu-18.04 - cc_compiler: gcc-8 - cxx_compiler: g++-8 - cxx_std: 17 - openexr_ver: v2.5.8 - pybind11_ver: v2.5.0 - simd: avx - setenvs: export EXTRA_DEP_PACKAGES=libjpeg-turbo8-dev - - desc: static libs gcc7 C++14 exr2.4 + - desc: static libs gcc9 C++17 exr2.4 nametag: linux-static runner: ubuntu-20.04 container: image: ubuntu-18.04 - cxx_compiler: g++-7 - cxx_std: 14 + cxx_compiler: g++-9 + cxx_std: 17 openexr_ver: v2.4.3 pybind11_ver: v2.6.2 setenvs: export BUILD_SHARED_LIBS=OFF diff --git a/INSTALL.md b/INSTALL.md index 3ad0cb4c62..20aba73b8e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -14,12 +14,11 @@ NEW or CHANGED MINIMUM dependencies since the last major release are **bold**. ### Required dependencies -- OIIO will not build at all without these - * C++14 or higher (also builds with C++17, and C++20) + * **C++17 or higher** (also builds with C++20) * The default build mode is C++17. This can be controlled by via the - CMake configuration flag: `-DCMAKE_CXX_STANDARD=14`, etc. - * ADVISORY: We expect that OIIO 2.6 in 2024 will require C++17 or higher. - * Compilers: gcc 6.1 - 13.1, clang 3.4 - 17, MSVS 2017 - 2019, - Intel icc 17+, Intel OneAPI C++ compiler 2022+. + CMake configuration flag: `-DCMAKE_CXX_STANDARD=20`, etc. + * Compilers: **gcc 9.3** - 13.1, **clang 5** - 17, MSVS 2017 - 2019 (**v19.14 + and up**), **Intel icc 19+**, Intel OneAPI C++ compiler 2022+. * **CMake >= 3.15** (tested through 3.28) * **OpenEXR/Imath >= 2.4** (recommended: 3.1 or higher; tested through 3.2 and main) (ADVISORY: We expect that OIIO 2.6 in 2024 will require OpenEXR >= 3.1) diff --git a/Makefile b/Makefile index a25f6b93fa..f14d343218 100644 --- a/Makefile +++ b/Makefile @@ -356,7 +356,7 @@ help: @echo " VERBOSE=1 Show all compilation commands" @echo " STOP_ON_WARNING=0 Do not stop building if compiler warns" @echo " MYCC=xx MYCXX=yy Use custom compilers" - @echo " CMAKE_CXX_STANDARD=14 C++ standard to build with (default is 17)" + @echo " CMAKE_CXX_STANDARD=20 C++ standard to build with (default is 17)" @echo " USE_LIBCPLUSPLUS=1 For clang, use libc++" @echo " GLIBCXX_USE_CXX11_ABI=1 For gcc, use the new string ABI" @echo " EXTRA_CPP_ARGS= Additional args to the C++ command" diff --git a/src/build-scripts/ci-startup.bash b/src/build-scripts/ci-startup.bash index 2522c28bc6..91c491b5dc 100755 --- a/src/build-scripts/ci-startup.bash +++ b/src/build-scripts/ci-startup.bash @@ -37,7 +37,7 @@ export OpenImageIO_CI=true export USE_NINJA=${USE_NINJA:=1} export CMAKE_GENERATOR=${CMAKE_GENERATOR:=Ninja} export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:=Release} -export CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD:=14} +export CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD:=17} export LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=$HOME/ext} export PATH=${LOCAL_DEPS_DIR}/dist/bin:$PATH diff --git a/src/build-scripts/gh-installdeps.bash b/src/build-scripts/gh-installdeps.bash index 7693d5e202..80c32677e6 100755 --- a/src/build-scripts/gh-installdeps.bash +++ b/src/build-scripts/gh-installdeps.bash @@ -118,13 +118,7 @@ else export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH - if [[ "$CXX" == "g++-6" ]] ; then - time sudo apt-get install -y g++-6 - elif [[ "$CXX" == "g++-7" ]] ; then - time sudo apt-get install -y g++-7 - elif [[ "$CXX" == "g++-8" ]] ; then - time sudo apt-get install -y g++-8 - elif [[ "$CXX" == "g++-9" ]] ; then + if [[ "$CXX" == "g++-9" ]] ; then time sudo apt-get install -y g++-9 elif [[ "$CXX" == "g++-10" ]] ; then time sudo apt-get install -y g++-10 @@ -132,6 +126,8 @@ else time sudo apt-get install -y g++-11 elif [[ "$CXX" == "g++-12" ]] ; then time sudo apt-get install -y g++-12 + elif [[ "$CXX" == "g++-13" ]] ; then + time sudo apt-get install -y g++-13 fi if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$USE_ICX" != "" ]] ; then diff --git a/src/cmake/compiler.cmake b/src/cmake/compiler.cmake index 7d2bf45b2c..c89bc79ed6 100644 --- a/src/cmake/compiler.cmake +++ b/src/cmake/compiler.cmake @@ -48,10 +48,10 @@ endmacro () ########################################################################### # C++ language standard # -set (CMAKE_CXX_MINIMUM 14) +set (CMAKE_CXX_MINIMUM 17) set (CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to build with (14, 17, 20, etc.) Minimum is ${CMAKE_CXX_MINIMUM}.") -set (DOWNSTREAM_CXX_STANDARD 14 CACHE STRING +set (DOWNSTREAM_CXX_STANDARD 17 CACHE STRING "C++ minimum standard to impose on downstream clients") set (CMAKE_CXX_STANDARD_REQUIRED ON) set (CMAKE_CXX_EXTENSIONS OFF) @@ -389,29 +389,6 @@ if (NOT MSVC AND NOT APPLE AND NOT ANDROID) endif () -########################################################################### -# Check if we need have std::filesystem on this platform. -# -cmake_push_check_state () -set (CMAKE_REQUIRED_DEFINITIONS ${CSTD_FLAGS}) -check_cxx_source_compiles("#include - int main() { std::filesystem::path p; return 0; }" - USE_STD_FILESYSTEM) -if (USE_STD_FILESYSTEM AND GCC_VERSION AND GCC_VERSION VERSION_LESS 9.0) - message (STATUS "Excluding USE_STD_FILESYSTEM because gcc is ${GCC_VERSION}") - set (USE_STD_FILESYSTEM OFF) -endif () -if (USE_STD_FILESYSTEM) - # Note: std::filesystem seems unreliable for gcc until 9 - message (STATUS "Compiler supports std::filesystem") - proj_add_compile_definitions (-DUSE_STD_FILESYSTEM) -else () - message (STATUS "Using Boost::filesystem") - proj_add_compile_definitions (-DUSE_BOOST_FILESYSTEM) -endif () -cmake_pop_check_state () - - ########################################################################### # Code coverage options # diff --git a/src/cmake/externalpackages.cmake b/src/cmake/externalpackages.cmake index e5d30f5f7c..a9e8bce32d 100644 --- a/src/cmake/externalpackages.cmake +++ b/src/cmake/externalpackages.cmake @@ -53,9 +53,6 @@ if (MSVC) endif () set (Boost_COMPONENTS thread) -if (NOT USE_STD_FILESYSTEM) - list (APPEND Boost_COMPONENTS filesystem) -endif () message (STATUS "Boost_COMPONENTS = ${Boost_COMPONENTS}") # The FindBoost.cmake interface is broken if it uses boost's installed # cmake output (e.g. boost 1.70.0, cmake <= 3.14). Specifically it fails @@ -232,8 +229,8 @@ if (LibRaw_FOUND AND LibRaw_VERSION VERSION_LESS 0.20 AND CMAKE_CXX_STANDARD VER # Currently, we issue the above warning and let them take their chances. # If we wish to disable the LibRaw<0.20/C++17 combination that may fail, # just uncomment the following two lines. - # set (LibRaw_FOUND 0) - # set (LIBRAW_FOUND 0) + set (LibRaw_FOUND 0) + set (LIBRAW_FOUND 0) endif () checked_find_package (OpenJPEG VERSION_MIN 2.0 diff --git a/src/doc/Doxyfile b/src/doc/Doxyfile index 759769d577..f69a0b1080 100644 --- a/src/doc/Doxyfile +++ b/src/doc/Doxyfile @@ -2164,7 +2164,6 @@ PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS \ OIIO_HOSTDEVICE= \ OIIO_NAMESPACE_BEGIN="namespace OIIO {" \ OIIO_NAMESPACE_END="}" \ - OIIO_CONSTEXPR14=constexpr \ OIIO_CONSTEXPR17=constexpr \ OIIO_CONSTEXPR20=constexpr \ OIIO_INLINE_CONSTEXPR="inline constexpr" \ diff --git a/src/include/OpenImageIO/detail/farmhash.h b/src/include/OpenImageIO/detail/farmhash.h index 96cc404933..c5c00652d1 100644 --- a/src/include/OpenImageIO/detail/farmhash.h +++ b/src/include/OpenImageIO/detail/farmhash.h @@ -83,19 +83,13 @@ // Make static inline 'const expr, if possible. Also, try to make CUDA friendly // for device code. #undef STATIC_INLINE -#if OIIO_CPLUSPLUS_VERSION >= 14 -# define HASH_CAN_USE_CONSTEXPR 1 -#endif -#define STATIC_INLINE OIIO_HOSTDEVICE inline OIIO_CONSTEXPR14 +#define HASH_CAN_USE_CONSTEXPR 1 +#define STATIC_INLINE OIIO_HOSTDEVICE inline constexpr // FARMHASH PORTABILITY LAYER: Runtime error if misconfigured #ifndef FARMHASH_DIE_IF_MISCONFIGURED -#ifdef HASH_CAN_USE_CONSTEXPR #define FARMHASH_DIE_IF_MISCONFIGURED -#else -#define FARMHASH_DIE_IF_MISCONFIGURED do { *(char*)(len % 17) = 0; } while (0) -#endif #endif // FARMHASH PORTABILITY LAYER: endianness and byteswapping functions diff --git a/src/include/OpenImageIO/oiioversion.h.in b/src/include/OpenImageIO/oiioversion.h.in index 9e2f84d696..58f0483007 100644 --- a/src/include/OpenImageIO/oiioversion.h.in +++ b/src/include/OpenImageIO/oiioversion.h.in @@ -185,7 +185,7 @@ namespace @PROJ_NAME@ = @PROJ_NAMESPACE_V@; #define OIIO_USING_IMATH_VERSION_MAJOR @Imath_VERSION_MAJOR@ #define OIIO_USING_IMATH_VERSION_MINOR @Imath_VERSION_MINOR@ -// Which CPP standard (11, 14, etc.) was this copy of OIIO *built* with? +// Which CPP standard (17, 20, etc.) was this copy of OIIO *built* with? #define OIIO_BUILD_CPP @CMAKE_CXX_STANDARD@ // DEPRECATED(2.1): old macros separately giving compatibility. diff --git a/src/include/OpenImageIO/platform.h b/src/include/OpenImageIO/platform.h index 99523f8bf9..fd3bbe34e2 100644 --- a/src/include/OpenImageIO/platform.h +++ b/src/include/OpenImageIO/platform.h @@ -64,7 +64,7 @@ // OIIO_INLINE_CONSTEXPR : inline constexpr variables, added in C++17. For // older C++, static constexpr. // -// Note: oiioversion.h defines OIIO_BUILD_CPP (set to 14, 17, etc.) +// Note: oiioversion.h defines OIIO_BUILD_CPP (set to 17, 20, etc.) // reflecting what OIIO itself was *built* with. In contrast, // OIIO_CPLUSPLUS_VERSION defined below will be set to the right number for // the C++ standard being compiled RIGHT NOW. These two things may be the @@ -77,18 +77,13 @@ # define OIIO_CONSTEXPR17 constexpr # define OIIO_CONSTEXPR20 constexpr # define OIIO_INLINE_CONSTEXPR inline constexpr -#elif (__cplusplus >= 201703L) +#elif (__cplusplus >= 201703L) || (defined(_MSC_VER) && _MSC_VER >= 1914) # define OIIO_CPLUSPLUS_VERSION 17 # define OIIO_CONSTEXPR17 constexpr # define OIIO_CONSTEXPR20 /* not constexpr before C++20 */ # define OIIO_INLINE_CONSTEXPR inline constexpr -#elif (__cplusplus >= 201402L) || (defined(_MSC_VER) && _MSC_VER >= 1914) -# define OIIO_CPLUSPLUS_VERSION 14 -# define OIIO_CONSTEXPR17 /* not constexpr before C++17 */ -# define OIIO_CONSTEXPR20 /* not constexpr before C++20 */ -# define OIIO_INLINE_CONSTEXPR static constexpr #else -# error "This version of OIIO is meant to work only with C++14 and above" +# error "This version of OIIO is meant to work only with C++17 and above" #endif // DEPRECATED(2.3): use C++14 constexpr @@ -113,12 +108,6 @@ # define __has_attribute(x) 0 #endif -// In C++17 (and some compilers before that), __has_include("blah.h") or -// __has_include() can test for presence of an include file. -#ifndef __has_include -# define __has_include(x) 0 -#endif - // Detect which compiler and version we're using @@ -389,7 +378,7 @@ #endif -// OIIO_FORCELINE is a function attribute that attempts to make the function +// OIIO_FORCEINLINE is a function attribute that attempts to make the function // always inline. On many compilers regular 'inline' is only advisory. Put // this attribute before the function return type, just like you would use // 'inline'. @@ -431,15 +420,11 @@ # define OIIO_CONST_FUNC #endif -// OIIO_MAYBE_UNUSED is a function or variable attribute that assures the -// compiler that it's fine for the item to appear to be unused. -#if OIIO_CPLUSPLUS_VERSION >= 17 || __has_cpp_attribute(maybe_unused) -# define OIIO_MAYBE_UNUSED [[maybe_unused]] -#elif defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || __has_attribute(unused) -# define OIIO_MAYBE_UNUSED __attribute__((unused)) -#else -# define OIIO_MAYBE_UNUSED -#endif +// OIIO_MAYBE_UNUSED is an annotator for function or variable attribute that +// assures the compiler that it's fine for the item to appear to be unused. +// Consider this deprecated (as of OIIO 3.0), you should favor C++17's +// [[maybe_unused]] attribute. +#define OIIO_MAYBE_UNUSED [[maybe_unused]] // DEPRECATED(1.9) name: #define OIIO_UNUSED_OK OIIO_MAYBE_UNUSED @@ -455,26 +440,18 @@ // OIIO_DEPRECATED before a function declaration marks it as deprecated in -// a way that will generate compile warnings if it is called. -#if OIIO_CPLUSPLUS_VERSION >= 14 || __has_cpp_attribute(deprecated) -# define OIIO_DEPRECATED(msg) [[deprecated(msg)]] -#elif defined(__GNUC__) || defined(__clang__) || __has_attribute(deprecated) -# define OIIO_DEPRECATED(msg) __attribute__((deprecated(msg))) -#elif defined(_MSC_VER) -# define OIIO_DEPRECATED(msg) __declspec(deprecated(msg)) -#else -# define OIIO_DEPRECATED(msg) -#endif +// a way that will generate compile warnings if it is called. This should +// itself be considered deprecated (as of OIIO 3.0) and code should use +// [[deprecated(msg)]] instead. +#define OIIO_DEPRECATED(msg) [[deprecated(msg)]] // OIIO_FALLTHROUGH at the end of a `case` label's statements documents that // the switch statement case is intentionally falling through to the code // for the next case. -#if OIIO_CPLUSPLUS_VERSION >= 17 || __has_cpp_attribute(fallthrough) -# define OIIO_FALLTHROUGH [[fallthrough]] -#else -# define OIIO_FALLTHROUGH -#endif +// Consider this deprecated (as of OIIO 3.0), you should favor C++17's +// [[fallthrough]] attribute. +#define OIIO_FALLTHROUGH [[fallthrough]] // OIIO_NODISCARD following a function declaration documents that the diff --git a/src/include/OpenImageIO/string_view.h b/src/include/OpenImageIO/string_view.h index 7329a1ac41..9ca0f1a1a7 100644 --- a/src/include/OpenImageIO/string_view.h +++ b/src/include/OpenImageIO/string_view.h @@ -194,10 +194,10 @@ class basic_string_view { constexpr iterator end() const noexcept { return m_chars + m_len; } constexpr const_iterator cbegin() const noexcept { return m_chars; } constexpr const_iterator cend() const noexcept { return m_chars + m_len; } - OIIO_CONSTEXPR17 reverse_iterator rbegin() const noexcept { return reverse_iterator (end()); } - OIIO_CONSTEXPR17 reverse_iterator rend() const noexcept { return reverse_iterator (begin()); } - OIIO_CONSTEXPR17 const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator (cend()); } - OIIO_CONSTEXPR17 const_reverse_iterator crend() const noexcept { return const_reverse_iterator (cbegin()); } + constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator (end()); } + constexpr reverse_iterator rend() const noexcept { return reverse_iterator (begin()); } + constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator (cend()); } + constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator (cbegin()); } // capacity constexpr size_type size() const noexcept { return m_len; } @@ -212,7 +212,7 @@ class basic_string_view { /// checking!). constexpr const_reference operator[](size_type pos) const { return m_chars[pos]; } /// Element access with bounds checking and exception if out of bounds. - OIIO_CONSTEXPR17 const_reference at(size_t pos) const + constexpr const_reference at(size_t pos) const { if (pos >= m_len) throw(std::out_of_range("OpenImageIO::string_view::at")); @@ -247,7 +247,7 @@ class basic_string_view { return basic_string_view(data() + pos, n); } - OIIO_CONSTEXPR17 int compare (basic_string_view x) const noexcept { + constexpr int compare (basic_string_view x) const noexcept { // N.B. char_traits::compare is constexpr for C++17 const int cmp = traits_type::compare (m_chars, x.m_chars, (std::min)(m_len, x.m_len)); return cmp != 0 ? cmp : int(m_len) - int(x.m_len); @@ -360,37 +360,37 @@ class basic_string_view { return npos; } - friend OIIO_CONSTEXPR17 bool + friend constexpr bool operator==(basic_string_view x, basic_string_view y) noexcept { return x.size() == y.size() ? (x.compare(y) == 0) : false; } - friend OIIO_CONSTEXPR17 bool + friend constexpr bool operator!=(basic_string_view x, basic_string_view y) noexcept { return x.size() == y.size() ? (x.compare(y) != 0) : true; } - friend OIIO_CONSTEXPR17 bool + friend constexpr bool operator<(basic_string_view x, basic_string_view y) noexcept { return x.compare(y) < 0; } - friend OIIO_CONSTEXPR17 bool + friend constexpr bool operator>(basic_string_view x, basic_string_view y) noexcept { return x.compare(y) > 0; } - friend OIIO_CONSTEXPR17 bool + friend constexpr bool operator<=(basic_string_view x, basic_string_view y) noexcept { return x.compare(y) <= 0; } - friend OIIO_CONSTEXPR17 bool + friend constexpr bool operator>=(basic_string_view x, basic_string_view y) noexcept { return x.compare(y) >= 0; diff --git a/src/include/OpenImageIO/ustring.h b/src/include/OpenImageIO/ustring.h index 6ca7f5f9b2..e3cb3a6414 100644 --- a/src/include/OpenImageIO/ustring.h +++ b/src/include/OpenImageIO/ustring.h @@ -931,13 +931,13 @@ class OIIO_UTIL_API ustringhash { } /// Test for equality with a char*. - OIIO_CONSTEXPR17 bool operator==(const char* str) const noexcept + constexpr bool operator==(const char* str) const noexcept { return m_hash == Strutil::strhash(str); } /// Test for inequality with a char*. - OIIO_CONSTEXPR17 bool operator!=(const char* str) const noexcept + constexpr bool operator!=(const char* str) const noexcept { return m_hash != Strutil::strhash(str); } diff --git a/src/libutil/filesystem.cpp b/src/libutil/filesystem.cpp index 27a2bfa2dd..81c6cb69a2 100644 --- a/src/libutil/filesystem.cpp +++ b/src/libutil/filesystem.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -15,7 +16,6 @@ #include #include #include -// #include #include #include #include @@ -35,26 +35,14 @@ # include #endif -#if defined(USE_STD_FILESYSTEM) -# include namespace filesystem = std::filesystem; using std::error_code; -#else -# include -namespace filesystem = boost::filesystem; -using boost::system::error_code; -#endif OIIO_NAMESPACE_BEGIN -// boost internally doesn't use MultiByteToWideChar (CP_UTF8,... -// to convert char* to wchar_t* because they do not know the encoding -// See boost/filesystem/path.hpp -// The only correct way to do this is to do the conversion ourselves. - inline filesystem::path u8path(string_view name) { @@ -87,18 +75,9 @@ pathstr(const filesystem::path& p) -#ifdef _MSC_VER -// fix for https://svn.boost.org/trac/boost/ticket/6320 -const std::string dummy_path = "../dummy_path.txt"; -const std::string dummy_extension - = filesystem::path(dummy_path).extension().string(); -#endif - std::string Filesystem::filename(string_view filepath) noexcept { - // To simplify dealing with platform-specific separators and whatnot, - // just use the Boost routines: try { return pathstr(u8path(filepath).filename()); } catch (...) { @@ -112,15 +91,6 @@ std::string Filesystem::extension(string_view filepath, bool include_dot) noexcept { std::string s; -#if !defined(USE_STD_FILESYSTEM) - if (filepath.find('.') == 0 && filepath.rfind('.') == 0) { - // Work around bug in boost::filesystem::path::extension(), where - // ".foo" thinks the extension is foo. But we know, and - // std::filesystem::path::extension() knows, that a file called ".foo" - // has no extension, that's just the base filename. - return s; - } -#endif try { s = pathstr(u8path(filepath).extension()); } catch (...) { @@ -392,18 +362,10 @@ Filesystem::is_executable(string_view path) noexcept error_code ec; auto stat = filesystem::status(u8path(path), ec); auto perm = stat.permissions(); -#ifdef USE_STD_FILESYSTEM return (perm & filesystem::perms::owner_exec) != filesystem::perms::none || (perm & filesystem::perms::group_exec) != filesystem::perms::none || (perm & filesystem::perms::others_exec) != filesystem::perms::none; -#else - return (perm & filesystem::perms::owner_exe) != filesystem::perms::no_perms - || (perm & filesystem::perms::group_exe) - != filesystem::perms::no_perms - || (perm & filesystem::perms::others_exe) - != filesystem::perms::no_perms; -#endif } @@ -494,24 +456,14 @@ Filesystem::temp_directory_path() std::string Filesystem::unique_path(string_view model) { -#ifdef USE_BOOST_FILESYSTEM - // Boost filesystem has unique_path(). - error_code ec; - filesystem::path p = filesystem::unique_path(u8path(model), ec); - return ec ? std::string() : pathstr(p); -#else // std::filesystem does not have unique_path(). Punt! -# if defined(_WIN32) - // boost internally doesn't use MultiByteToWideChar (CP_UTF8,... - // to convert char* to wchar_t* because they do not know the encoding - // See boost/filesystem/path.hpp - // The only correct way to do this is to do the conversion ourselves +#if defined(_WIN32) std::wstring modelStr = Strutil::utf8_to_utf16wstring(model); std::wstring name; -# else - std::string modelStr = model.str(); +#else + std::string modelStr = model; std::string name; -# endif +#endif static const char chrs[] = "0123456789abcdef"; static std::mt19937 rg { std::random_device {}() }; static std::uniform_int_distribution pick(0, 15); @@ -523,18 +475,17 @@ Filesystem::unique_path(string_view model) for (size_t i = 0, e = modelStr.size(); i < e; ++i) if (name[i] == '%') name[i] = chrs[pick(rg)]; -# if defined(_WIN32) +#if defined(_WIN32) if (!exists(Strutil::utf16_to_utf8(name))) -# else +#else if (!exists(name)) -# endif +#endif break; } -# if defined(_WIN32) +#if defined(_WIN32) return Strutil::utf16_to_utf8(name); -# else +#else return name; -# endif #endif } diff --git a/src/libutil/filesystem_test.cpp b/src/libutil/filesystem_test.cpp index 9e25558d06..08fa618adc 100644 --- a/src/libutil/filesystem_test.cpp +++ b/src/libutil/filesystem_test.cpp @@ -224,7 +224,10 @@ test_file_status() std::cout << "Testing is_directory, is_regular, is_executable\n"; OIIO_CHECK_ASSERT(Filesystem::is_regular("testfile")); OIIO_CHECK_ASSERT(!Filesystem::is_directory("testfile")); +#ifndef _WIN32 + // Directories look "executable" on Unix, not on Windows OIIO_CHECK_ASSERT(!Filesystem::is_executable("testfile")); +#endif OIIO_CHECK_ASSERT(!Filesystem::is_regular("testdir")); OIIO_CHECK_ASSERT(Filesystem::is_directory("testdir")); OIIO_CHECK_ASSERT(!Filesystem::is_executable("testdir")); diff --git a/src/oiiotool/printinfo.cpp b/src/oiiotool/printinfo.cpp index 1be4d32ecb..c12ab1656c 100644 --- a/src/oiiotool/printinfo.cpp +++ b/src/oiiotool/printinfo.cpp @@ -210,7 +210,7 @@ dump_data(std::ostream& out, ImageInput* input, } } else { - OIIO_UNUSED_OK bool ok = true; + OIIO_MAYBE_UNUSED bool ok = true; PRINTINFO_DISPATCH_TYPES(ok, "dump_flat_data", dump_flat_data, spec.format, out, input, opt, subimage); } diff --git a/testsuite/cmake-consumer/CMakeLists.txt b/testsuite/cmake-consumer/CMakeLists.txt index d1238453a8..ce84f748e5 100644 --- a/testsuite/cmake-consumer/CMakeLists.txt +++ b/testsuite/cmake-consumer/CMakeLists.txt @@ -12,8 +12,8 @@ endif () message (STATUS "Building ${PROJECT_NAME} ${PROJECT_VERSION} - ${CMAKE_BUILD_TYPE}") -# Use C++14 -set (CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard to prefer (14, 17, etc.)") +# Use C++17 +set (CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to prefer (17, 20, etc.)") set (CMAKE_CXX_STANDARD_REQUIRED ON) set (CMAKE_CXX_EXTENSIONS OFF) diff --git a/testsuite/docs-examples-cpp/CMakeLists.txt b/testsuite/docs-examples-cpp/CMakeLists.txt index c452f81360..27b4a1cdd7 100644 --- a/testsuite/docs-examples-cpp/CMakeLists.txt +++ b/testsuite/docs-examples-cpp/CMakeLists.txt @@ -12,8 +12,8 @@ endif () message (STATUS "Building ${PROJECT_NAME} ${PROJECT_VERSION} - ${CMAKE_BUILD_TYPE}") -# Use C++14 -set (CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard to prefer (14, 17, etc.)") +# Use C++17 +set (CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to prefer (17, 20, etc.)") set (CMAKE_CXX_STANDARD_REQUIRED ON) set (CMAKE_CXX_EXTENSIONS OFF)