1

I am writing a library (just for learning) which utilizes std::filesystem. It works fine on MSVC however by default LTS releases of Linux like Ubuntu ships with GCC 6.x and clang in the official repository is 3.8 which doesn't have std::filesystem instead I have to use std::experimental::filesystem. How may I workaround this problem so that I can support GCC 6, GCC 8+ (where std::filesystem works), Clang 3.8, latest Clang and MSVC? I am using CMAKE as my build system

Shivam Jha
  • 88
  • 1
  • 8

3 Answers3

3

Conditional compilation may help:

#if(defined(_MSC_VER) or (defined(__GNUC__) and (7 <= __GNUC_MAJOR__)))
using n_fs = ::std::filesystem;
#else
using n_fs = ::std::experimental::filesystem;    
#endif
user7860670
  • 35,849
  • 4
  • 58
  • 84
2

I fixed my problem in the following way:

I added the following bunch of code in the project's CMakeLists.txt file

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.4)
        message(FATAL_ERROR "You are on an extremely old version of GCC. Please update your compiler to at least GCC 5.4, preferably latest")
    elseif (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
        message(WARNING "Old Verison of GCC detected. Using Legacy C++ support")
        target_link_libraries(${PROJECT_NAME} -lstdc++fs)
        target_compile_definitions(${PROJECT_NAME} PUBLIC LEGACY_CXX)
    endif()
endif()

And in my CPP file, I did this:

#ifdef LEGACY_CXX
#include <experimental/filesystem>
namespace n_fs = ::std::experimental::filesystem;
#else
#include <filesystem>
namespace n_fs = ::std::filesystem;
#endif

Here's the commit if anyone want to refer to.

Shivam Jha
  • 88
  • 1
  • 8
0

"How may I workaround this problem" - by installing a newer compiler/standard library. Or by not using std::filesystem.

For example, on RedHat and CentOS you can install devtoolset-8 to get access to a newer (and supported) compiler than what the base system provides. Other Linux distributions may have similar options.

You can also compile a newer compiler + std lib yourself from source. That's in itself not too difficult, but you need to be careful to then also ship the new libraries. And testing compatibility with the base distro libraries etc is on you.

You can also, as per @VTT's answer, use conditional compilation to fall back to std::experimental::filesystem if that's all your toolchain supports and you are ok with that.

Of you don't want to change compiler and using std::experimental::filesystem is not ok (or your compiler/standard library doesn't even support that), then your only option is to use OS native functions.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • Surprised this was downvoted. Could the downvoter please explain *why*? – Jesper Juhl Apr 21 '19 at 13:15
  • I'm not the down voter however I feel you didn't get my question (in that case ofcourse that's my fault). – Shivam Jha Apr 21 '19 at 14:21
  • It's not about me installing xyz versions of compiler. It's about the user of my Library who might not want to update to a recent version of GCC maybe due to some reasons or might be just too lazy or don't have the know how of upgrading their compiler. – Shivam Jha Apr 21 '19 at 14:23
  • 1
    @ShivamJha if you want to support people using older compilers/libraries, then you have to only use facilities available by the oldest toolchain you wish to support or provide alternative implentations for users of old stuff you want to support. Or you just need to say; this library uses zyz and requires foo from your toolchain and if you cannot meet those requirements, then don't use my library. – Jesper Juhl Apr 21 '19 at 15:47