diff --git a/build-support/custom-modules/ns3-compiler-workarounds.cmake b/build-support/custom-modules/ns3-compiler-workarounds.cmake index 6f5e96ecc..0841f66ca 100644 --- a/build-support/custom-modules/ns3-compiler-workarounds.cmake +++ b/build-support/custom-modules/ns3-compiler-workarounds.cmake @@ -48,3 +48,29 @@ if(${MISSING_OSTREAM_NULLPTR_OPERATOR}) ${CMAKE_CURRENT_SOURCE_DIR}/build-support/compiler-workarounds/ostream-operator-nullptr.h ) endif() + +# Some compilers (e.g. GCC < 9.1 and Clang < 9) do not link +# std::filesystem/std::experimental::filesystem by default. +# If the sample program can be linked, it means it is +# indeed linked by default. Otherwise, we link it manually. +# https://en.cppreference.com/w/cpp/filesystem +check_cxx_source_compiles( + " + # ifdef __cpp_lib_filesystem + #include + namespace fs = std::filesystem; + #else + #include + namespace fs = std::experimental::filesystem; + #endif + int main() + { + std::string path = \"/\"; + return !fs::exists (path); + } + " + FILESYSTEM_LIBRARY_IS_LINKED +) +if(NOT FILESYSTEM_LIBRARY_IS_LINKED) + link_libraries(-lstdc++fs) +endif() diff --git a/build-support/macros-and-definitions.cmake b/build-support/macros-and-definitions.cmake index e34384c93..411793353 100644 --- a/build-support/macros-and-definitions.cmake +++ b/build-support/macros-and-definitions.cmake @@ -221,6 +221,12 @@ if(${CLANG} AND APPLE) set(STATIC_LINK_FLAGS) endif() +# Include CMake files used for compiler checks +include(CheckIncludeFile) # Used to check a single C header at a time +include(CheckIncludeFileCXX) # Used to check a single C++ header at a time +include(CheckIncludeFiles) # Used to check multiple headers at once +include(CheckFunctionExists) + macro(SUBDIRLIST result curdir) file(GLOB children RELATIVE ${curdir} ${curdir}/*) set(dirlist "") @@ -1078,11 +1084,6 @@ macro(process_options) set(INT64X64_USE_CAIRO TRUE) endif() - include(CheckIncludeFile) # Used to check a single C header at a time - include(CheckIncludeFileCXX) # Used to check a single C++ header at a time - include(CheckIncludeFiles) # Used to check multiple headers at once - include(CheckFunctionExists) - # Check for required headers and functions, set flags if they're found or warn # if they're not found check_include_file("stdint.h" "HAVE_STDINT_H") diff --git a/src/core/model/system-path.cc b/src/core/model/system-path.cc index 5ebff339e..d4c0a38c5 100644 --- a/src/core/model/system-path.cc +++ b/src/core/model/system-path.cc @@ -25,12 +25,28 @@ #include #include // getenv #include // strlen -#include #include #include #include #include +// Some compilers such as GCC < 8 (Ubuntu 18.04 +// ships with GCC 7) do not ship with the +// std::filesystem header, but with the +// std::experimental::filesystem header. +// Since Clang reuses these headers and the libstdc++ +// from GCC, we need to either use the experimental +// version or require a more up-to-date GCC. +// we use the "fs" namespace to prevent collisions +// with musl libc. +# ifdef __cpp_lib_filesystem + #include + namespace fs = std::filesystem; +#else + #include + namespace fs = std::experimental::filesystem; +#endif + #ifdef __APPLE__ #include #endif /* __APPLE__ */ @@ -84,13 +100,13 @@ ReadFilesNoThrow (std::string path) { NS_LOG_FUNCTION (path); std::list files; - if (!std::filesystem::exists (path)) + if (!fs::exists (path)) { return std::make_tuple (files, true); } - for (auto &it : std::filesystem::directory_iterator (path)) + for (auto &it : fs::directory_iterator (path)) { - if (!it.is_directory ()) + if (!fs::is_directory(it.path())) { files.push_back (it.path ().filename ().string ()); } @@ -341,9 +357,9 @@ MakeDirectories (std::string path) NS_LOG_FUNCTION (path); std::error_code ec; - if (!std::filesystem::exists (path)) + if (!fs::exists (path)) { - std::filesystem::create_directories (path, ec); + fs::create_directories (path, ec); } if (ec.value ())