Pourquoi Apple clang interdire le C++11 thread_local lorsque "officielle" clang prend en charge
Ci-dessous est un simple programme qui teste à l'aide de C++11 thread_local variable de non-type de POD dans une bibliothèque partagée.
Si j'utilise homebrew clang, cela fonctionne très bien:
> /usr/local/Cellar/llvm/3.5.0_2/bin/clang --version
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-apple-darwin14.0.0
Thread model: posix
> cmake .. -G Ninja -DCMAKE_C_COMPILER=/usr/local/Cellar/llvm/3.5.0_2/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/Cellar/llvm/3.5.0_2/bin/clang++
-- The C compiler identification is Clang 3.5.0
-- The CXX compiler identification is Clang 3.5.0
-- Check for working C compiler using: Ninja
-- Check for working C compiler using: Ninja -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler using: Ninja
-- Check for working CXX compiler using: Ninja -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
> ninja all
...
> ./main
XXX LifeCycle::LifeCycle 0x7fedc0c04b90
X before: -17
XXX LifeCycle::LifeCycle 0x7fedc0c04c10
X before in thread: -17
X after in thread: 2
XXX LifeCycle::~LifeCycle 0x7fedc0c04c10
X after: 1
XXX LifeCycle::~LifeCycle 0x7fedc0c04b90
Cependant, si j'essaie d'utiliser Apple Clang, je reçois un message d'erreur disant qu'il n'est pas pris en charge:
> /usr/bin/clang --version
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix
> cmake .. -G Ninja -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++
-- The C compiler identification is AppleClang 6.0.0.6000056
-- The CXX compiler identification is AppleClang 6.0.0.6000056
-- Check for working C compiler using: Ninja
-- Check for working C compiler using: Ninja -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler using: Ninja
-- Check for working CXX compiler using: Ninja -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to:
> ninja all
[1/4] Building CXX object CMakeFiles/lib.dir/lib.cpp.o
FAILED: /usr/bin/clang++ -Dlib_EXPORTS -Wall -std=c++11 -mmacosx-version-min=10.7 -stdlib=libc++ -fPIC -MMD -MT CMakeFiles/lib.dir/lib.cpp.o -MF CMakeFiles/lib.dir/lib.cpp.o.d -o CMakeFiles/lib.dir/lib.cpp.o -c ../lib.cpp
../lib.cpp:23:5: error: thread-local storage is unsupported for the current target
thread_local LifeCycle lc;
^
1 error generated.
ninja: build stopped: subcommand failed.
Quelqu'un peut-il offrir tout de comprendre pourquoi Apple clang variante lâche refuse d'honorer thread_local, malgré le fait que le compilateur prend en charge, et le code généré s'affiche à travailler?
lib.h:
#pragma once
int doit(int) __attribute__((__visibility__("default")));
lib.cpp:
#include "lib.h"
#include <thread>
#include <cstdlib>
#include <cstdio>
namespace {
class LifeCycle {
public:
LifeCycle()
: x(-17) {
printf("XXX LifeCycle::LifeCycle %p\n", this);
}
~LifeCycle() {
printf("XXX LifeCycle::~LifeCycle %p\n", this);
}
int x;
};
thread_local LifeCycle lc;
} //namespace
int doit(int arg) {
printf("X before: %d\n", lc.x);
lc.x = arg;
std::thread xwriter([arg]() {
if (lc.x == arg)
abort();
printf("X before in thread: %d\n", lc.x);
lc.x = arg + 1;
printf("X after in thread: %d\n", lc.x);
});
xwriter.join();
printf("X after: %d\n", lc.x);
return (lc.x == arg ? EXIT_SUCCESS : EXIT_FAILURE);
}
main.cpp:
#include "lib.h"
int main(int argc, char* argv[]) {
return doit(argc);
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.1)
set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -mmacosx-version-min=10.7 -stdlib=libc++")
add_library(lib SHARED lib.cpp)
add_executable(main main.cpp)
target_link_libraries(main lib)
- Apple officiel de clang version de XCode 6 est basé sur llvm-3.5, et clang-3.5 prend en charge thread_local sur Darwin. Je crois qu'il l'a dans des versions antérieures à clang-3.5 ainsi.
- Probablement un bug: stackoverflow.com/a/23850891/1392778
Vous devez vous connecter pour publier un commentaire.
Le compilateur clang fourni avec Xcode 8 et les versions ultérieures prennent en charge le C++11
thread_local
mot-clé. Cette fonctionnalité a été ajoutée à l'Xcode beta 8 tel que discuté dans la WWDC 2016 vidéo "Quoi de neuf dans LLVM", en commençant à 5:50 marque. (externe verbatim)L'exemple de programme figurant dans la question compile et s'exécute avec Xcode 8 GM sous OS X 10.11.6 et produit le résultat attendu. Il a ensuite été re-testé avec Xcode 9.3 sous macOS 10.13.4, et avec Xcode 10.2.1 sous macOS 10.14.4, et continue à se comporter comme prévu.
Concernant iOS, j'ai trouvé par l'expérimentation que
thread_local
est pris en charge pour iOS 9 et plus tard, mais pas pour iOS 8.4 ou plus tôt.Pour Xcode 7.x et versions antérieures, ici, est une réponse à partir de 2014 d'une Pomme ingénieur sur l'ancien site Apple Developer Forum (qui n'est plus accessible):
Le billet suivant, confirme que
thread_local
est toujours pas pris en charge dans Xcode 6.3.thread_local
le 10 mai 2016 🙁 je ne vois pas de plans ou de l'horizon pour le soutien de cette fonction, qui est nul parce quethread_local
aurait aidé à résoudre un problème de performance pour moi.thread_local
, "the real deal" clang, et de la dépendance des bibliothèques telles que coup de pouce, MPFR, GMP, et MPI? Actuellement, je m'attends à toutes être installé via un gestionnaire de paquets comme Homebrew.thread_local
, comme annoncé lors de la WWDC de cette année. Cela fournit une autre option si vos utilisateurs sont soit à l'aise avec un bêta compilateur ou peut attendre jusqu'à l'automne.thread_local
prouve pourquoi toutes les critiques ci-dessus sont fausses. Ils ont attendu jusqu'à ce qu'ils avaient une bonne mise en œuvre qu'ils pourraient garantie serait stable à jamais. Que la philosophie est exactement pourquoi libSystem (Apple "CRT") a jamais cassé la compatibilité binaire, tandis que Microsoft a un nouveaumsvcrXYZ.dll
/vcruntimeXYZ.dll
avec chaque compilateur changement.thread_local
, testé 20 septembre 2016. je suis par hasard intéressés par ce que @alexchandel moyens sur la façon dont ils ont mis en œuvre, mais n'en ai trop dans mon assiette à la recherche pleinement.thread_local
est pris en charge pour iOS 9 et plus tard, mais pas pour iOS 8.4 ou plus tôt. Je n'ai pas d'explication pour cela; il ressemble le support TLS est compilé dans l'application Mac, mais l'application iOS apparemment s'appuie sur l'OS support d'exécution qui n'est pas présent avant d'iOS 9.Selon http://clang.llvm.org/cxx_status.html:
Je crois que la version homebrew de clang utilise un autre C++ runtime.