spin_eight
spin_eight

Reputation: 4025

Why I can't include some headers from C++17 on mac

My system: macOS Catalina(10.15.4)

Brew config
Clang: 11.0 build 1103
Git: 2.21.0 => /usr/local/bin/git
Curl: 7.64.1 => /usr/bin/curl
Java: 1.8.0_101
macOS: 10.15.4-x86_64
CLT: 11.4.1.0.1.1586360307
Xcode: N/A

Issue: can't include some C++17 headers: execution, filesystem
while can include the other like: any, variant.
Most of C++17 features like structured binding, template parameters deduction etc works.

Example. Trying to build a file with the following code snippet:

#include <numeric>
#include <vector>
#include <iostream>
#include <iterator>
#include <string>
#include <sstream>
#include <utility> //std::pair
#include <tuple> // std::tie
#include <algorithm> // std::clamp

#include <optional> // std::optional

#include <map>
// ... other stuff

#include <execution>
namespace parallel_algoritmhs {
  void show() {
    std::vector<int> v = {1,2,3,4,5,6};
    std::for_each(std::execution::par, v.begin(), v.end(), [](auto& e) {e+=100;});
int main() {
//... use 
}

I am building with:

g++ -std=c++17 -fsanitize=undefined -fno-sanitize-recover=all -o main c++17.cpp

Update: I have tried suggested:

clang -std=c++17 -fsanitize=undefined -fno-sanitize-recover=all -o main c++17.cpp
clang++ -std=c++17 -fsanitize=undefined -fno-sanitize-recover=all -o main c++17.cpp

And getting the same result.

If I comment out code snippet related to different execution strategies, while leaving other code snippets like:

#include <any>
namespace any {
  void show() {
    std::any v = 42;
    v = 4.2;
    v = std::string{"hello"};
    std::cout << std::any_cast<std::string>(v) << '\n';
  }
}

namespace map_cpp17 {
  void show() {
    std::map<int, std::string> myMap{ { 1, "Gennady" }, { 2, "Petr" }, { 3, "Makoto" } };
    auto node = myMap.extract(2);
    node.key() = 42;
    myMap.insert(std::move(node));

    std::map<int, std::string> m1{ { 1, "aa" }, { 2, "bb" }, { 3, "cc" } };
    std::map<int, std::string> m2{ { 4, "dd" }, { 5, "ee" }, { 6, "ff" } };
    m1.merge(m2);

    std::map<int, std::string> m; m.emplace(1, "aaa"); m.emplace(2, "bbb"); m.emplace(3, "ccc");
    auto [it1, inserted1] = m.insert_or_assign(3, "ddd"); std::cout << inserted1; // 0
    auto [it2, inserted2] = m.insert_or_assign(4, "eee"); std::cout << inserted2; // 1
  }
}

Everything compiles

With

#include <execution>

getting:

fatal error: 'execution' file not found  
#include <execution>

I wonder what might be the problem behind that and how to fix this. Thank you!

Update 2: brew info llvm:

llvm: stable 10.0.0 (bottled), HEAD [keg-only]
Next-gen compiler infrastructure
https://llvm.org/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/llvm.rb
==> Dependencies
Build: cmake ✔, [email protected] ✘
Required: libffi ✘
==> Requirements
Build: xcode ✘
==> Options
--HEAD
    Install HEAD version
==> Caveats
To use the bundled libc++ please add the following LDFLAGS:
  LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"

llvm is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

Update 3: clang --version

Apple clang version 11.0.3 (clang-1103.0.32.59)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Upvotes: 0

Views: 2706

Answers (1)

HTNW
HTNW

Reputation: 29193

You're not actually using the Clang you installed. The official LLVM Clang doesn't have a version 11.0! LLVM is only on version 10.0 (check brew info llvm). You're using Apple Clang, which comes with its own installation of libc++. Presumably to catch this exact type of problem, Apple Clang responds to clang --version/clang++ --version with the "future" version 11.0. However, Apple's distribution is actually a bit behind the state of the art, and it simply isn't updated to these features.

When you install LLVM with Homebrew, it doesn't automatically set it up the new clang/clang++ to be easily callable, because things might expect clang to specifically mean "Apple Clang" and break if that changes. You should add /usr/local/opt/llvm/bin (which Homebrew symlinks into the LLVM installation) to your PATH (which is where your shell and other programs search for programs). In an already running shell session

export PATH="/usr/local/opt/llvm/bin:$PATH"

will switch to using the newly installed LLVM Clang until you exit the session. Putting this line in a shell startup file, like ~/.bash_profile, will set up this adjustment to be applied every time you open a new shell.

Alternatively, like @Eljay does, you could just manually type out the full path to the new clang/clang++ (/usr/local/opt/llvm/bin/clang/-++), thereby bypassing the search into PATH, but that's a pain. In any case, you'll know you got it right if clang --version/clang++ --version gives you 10.0.0.

Upvotes: 1

Related Questions