Correct way to link std::filesystem with GCC 8?

As noted at the bottom of the page here: Filesystem library - cppreference.com, using std::filesystem from C++17 with GCC 8 requires adding -lstdc++fs to the linker options. GCC 8 is the system compiler for Debian 10.

What is the cleanest/correct way to deal with this within CMake?

After digging around on Github, I have seen projects that deal with this simply by matching on CMAKE_CXX_COMPILER_ID and adding the relevant library, which I have tried here: riesling/CMakeLists.txt at stdfs · spinicist/riesling · GitHub. I am concerned that this may not be optimal/robust, hence I’m wondering if there is a better way. Thanks.

There is no special handling in CMake for this because it is highly dependent on the compiler as well as the version. For example, more recent versions of gcc do not require anymore this library because fs is part of the standard C++ runtime.

1 Like

Thanks - that’s exactly why I am asking this question. What’s the most idiomatic way to handle this in a graceful way? What extra lines do I have to add to CMakeLists.txt to deal with it across as wide a number of compilers and versions as possible?

As far as I can tell, higher versions of GCC still ship that library, even if the main libstdc++ also includes the symbols. So I think it’s okay to not worry about the specific GCC version?

You have to do exactly what you currently do: check compiler kind and version to ensure correct configuration to use filesystem.

But, FYI, most of recent compilers include fs as part of the standard C++ runtime because it is now part of the language standard (no longer a Technical Specification).

I had the same issue in OSM2go, and that’s how I solved it:

Maybe I’ll rewrite it to use targets one day.

Eike

At my old employer I solved it with the following function:

function( set_required_build_settings_for_GCC8 )
    # Always link with libstdc++fs.a when using GCC 8.
    # Note: This command makes sure that this option comes pretty late on the cmdline.
    link_libraries( "$<$<AND:$<CXX_COMPILER_ID:GNU>,$<VERSION_LESS:$<CXX_COMPILER_VERSION>,9.0>>:-lstdc++fs>" )
endfunction()

I had to call that function pretty early in the top-level CMakeLists.txt file in order to make sure that it is used everywhere.
Of course, you should probably instruct your linker to only link with libraries if they are used at all. (E.g. use add_link_options( LINKER:--as-needed ).)

2 Likes

@Dakon and @dbahadir Thank you for the suggestions, very helpful.

I’m going to try the one from @dbahadir as it’s explicitly only GCC 8 I’m worried about, not the pre-C++17 experimental filesystem support.

The one-liner with the GCC check isn’t good enough to cover clang (and potentially other compilers).

I have just been pointed to the following issue:
https://gitlab.kitware.com/cmake/cmake/-/issues/17834