Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does llvm 9 support std::filesystem on versions of the mac prior to 10.15?

I have an old Mac (circa 2009) running El Capitan version 10.11.6. Apple doesn't allow further updates of its OS on my machine, but through Macports it serves as a fine development environment for non-Apple-specific software.

I'm compiling with g++ 9.2, which supports std::filesystem out of the box, and with clang 8.0, which doesn't. (Using each compiler's native standard library, in each case.) And I'm compiling with --std=c++2a.

I've noticed the llvm 9 is supposed to support std::filesystem out of the box (https://libcxx.llvm.org/docs/UsingLibcxx.html#using-filesystem), so I downloaded clang/llvm 9 through Macports. Unfortunately, I'm hitting a snag.

Minimal code to reproduce error is a simplification of the example from cppreference.com (https://en.cppreference.com/w/cpp/filesystem/path/path)

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int
main()
{
   fs::path p1 = "/usr/lib/sendmail.cf";

   std::cout << "p1 = " << p1 << '\n';
}

And here's the CmakeLists.txt

cmake_minimum_required(VERSION 3.15.5)
project(bug LANGUAGES CXX)
add_executable (bug main.cpp)
target_compile_options(bug PRIVATE "-std=c++2a")

And here's the compiler's complaints:

[build] Starting build
[proc] Executing command: /opt/local/bin/cmake --build ~/temp/build/debug/clang --config debug --target all -- -j 10
[build] [1/2  50% :: 1.598] Building CXX object CMakeFiles/bug.dir/main.cpp.o
[build] FAILED: CMakeFiles/bug.dir/main.cpp.o 
[build] /opt/local/bin/clang++    -g   -std=c++2a -MD -MT CMakeFiles/bug.dir/main.cpp.o -MF CMakeFiles/bug.dir/main.cpp.o.d -o CMakeFiles/bug.dir/main.cpp.o -c ../../../main.cpp
[build] ../../../main.cpp:9:8: error: 'path' is unavailable: introduced in macOS 10.15
[build]    fs::path p1 = "/usr/lib/sendmail.cf";
[build]        ^
[build] /opt/local/libexec/llvm-9.0/bin/../include/c++/v1/filesystem:738:24: note: 'path' has been explicitly marked unavailable here
[build] class _LIBCPP_TYPE_VIS path {
...

Working backward, I find this bit of code in /opt/local/libexec/llvm-9.0/include/c++/v1/__config:

#  define _LIBCPP_AVAILABILITY_FILESYSTEM                                      \
     __attribute__((availability(macosx,strict,introduced=10.15)))             \
     __attribute__((availability(ios,strict,introduced=13.0)))                 \
     __attribute__((availability(tvos,strict,introduced=13.0)))                \
     __attribute__((availability(watchos,strict,introduced=6.0)))

As far as I can determine, this #define is the ultimate cause of the above error message.

So, my questions are:

  • Is this a bug with LLVM? After all, GCC doesn't introduce a dependency between std::filesystem and the OS version.
  • Is this a bug with Macports? Maybe they didn't use the correct flags when building?
  • If I were to build LLVM and Clang natively, can I work around this issue?
  • Is it an issue at all? Maybe the good folks at LLVM know something that the good folks at GCC don't.

NOTE: There's a similar question involving clang/llvm downloaded through Homebrew. Unfortunately, the commentary was not helpful. [LLVM-9 clang-9 OSX]: std::filesystem::path unrecognized

like image 344
Curious Avatar asked Nov 07 '22 12:11

Curious


1 Answers

I've been looking through LLVM and encountered the following lines:

// Decide whether to use availability macros.
#if !defined(_LIBCPP_BUILDING_LIBRARY) &&                                      \
    !defined(_LIBCPP_DISABLE_AVAILABILITY) &&                                  \
    __has_feature(attribute_availability_with_strict) &&                       \
    __has_feature(attribute_availability_in_templates)
#  ifdef __APPLE__
#    define _LIBCPP_USE_AVAILABILITY_APPLE
#  endif
#endif

So I passed -D_LIBCPP_DISABLE_AVAILABILITY to the compiler and it worked! I doubt that it's a valid solution, but it may help someone. Another option could be sticking to https://github.com/gulrak/filesystem which is basically std::filesystem, but outside of the standard library.

Answering some of your questions:

Is this a bug with LLVM? After all, GCC doesn't introduce a dependency between std::filesystem and the OS version.

Well, it's not a bug, but yes, it's a feature of LLVM and it seems that it's made especially for Apple.

Is this a bug with Macports? Maybe they didn't use the correct flags when building?

No, it's not a bug of Macports or Homebrew.

If I were to build LLVM and Clang natively, can I work around this issue?

As you could see this availability feature is in the sources, so it seems that it doesn't matter if you build it from sources or using a package manager.

Is it an issue at all? Maybe the good folks at LLVM know something that the good folks at GCC don't.

Unfortunately, I can't state anything here, but it should've been done for a reason.

like image 55
Gleb Ignatev Avatar answered Nov 15 '22 07:11

Gleb Ignatev