xcode 为什么当“官方”clang 支持 C++11 thread_local 时,Apple clang 不允许它
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28094794/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does Apple clang disallow C++11 thread_local when 'official' clang supports it
提问by acm
Below is a simple program that tests using a C++11 thread_local variable of non-POD type in a shared library.
下面是一个简单的程序,它使用共享库中非 POD 类型的 C++11 thread_local 变量进行测试。
If I use homebrew clang, this works fine:
如果我使用自制的叮当声,这很好用:
> /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
However, if I try to use Apple Clang, I get an error message saying that it is not supported:
但是,如果我尝试使用 Apple Clang,我会收到一条错误消息,指出它不受支持:
> /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.
Can anyone offer any insight into why Apple's clang variant cowardly refuses to honor thread_local, despite the fact that the underlying compiler supports it, and the generated code appears to work?
任何人都可以深入了解为什么 Apple 的 clang 变体懦弱地拒绝尊重 thread_local,尽管底层编译器支持它,并且生成的代码似乎可以工作?
lib.h:
库.h:
#pragma once
int doit(int) __attribute__((__visibility__("default")));
lib.cpp:
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:
主.cpp:
#include "lib.h"
int main(int argc, char* argv[]) {
return doit(argc);
}
CMakeLists.txt:
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)
回答by rsfinn
The clang compiler included with Xcode 8 and later supports the C++11 thread_local
keyword. This functionality was added to the Xcode 8 beta as discussed in the WWDC 2016 video "What's New in LLVM", beginning at the 5:50 mark. (external transcript)
Xcode 8 及更高版本中包含的 clang 编译器支持 C++11thread_local
关键字。如WWDC 2016 视频“LLVM 中的新功能”中所述,此功能已添加到 Xcode 8 测试版,从5:50开始。(外部成绩单)
The sample program listed in the question compiles and runs with Xcode 8 GM under OS X 10.11.6 and produces the intended output. It has subsequently been re-tested with Xcode 9.3 under macOS 10.13.4, and with Xcode 10.2.1 under macOS 10.14.4, and continues to behave as intended.
问题中列出的示例程序在 OS X 10.11.6 下使用 Xcode 8 GM 编译和运行,并产生预期的输出。它随后在 macOS 10.13.4 下的 Xcode 9.3 和 macOS 10.14.4 下的 Xcode 10.2.1 进行了重新测试,并继续按预期运行。
Regarding iOS, I found by experimentation that thread_local
is supported for iOS 9 and later, but not for iOS 8.4 or earlier.
关于 iOS,我通过实验发现thread_local
iOS 9 及更高版本支持,但不支持 iOS 8.4 或更早版本。
For Xcode 7.x and earlier, here is an answer from 2014 from an Apple engineer on the old Apple Developer Forum (no longer accessible):
对于 Xcode 7.x 及更早版本,以下是 2014 年 Apple 工程师在旧 Apple Developer Forum(不再可访问)上的回答:
We don't support the thread_local implementation from the open-source Clang because we believe we can provide a higher-performance implementation for our platforms using various features in the dynamic linker. Such an implementation would be ABI-incompatible with the implementation in the open-source Clang, so we won't support thread_local until we get an implementation we can live with for the foreseeable future.
我们不支持来自开源 Clang 的 thread_local 实现,因为我们相信我们可以使用动态链接器中的各种功能为我们的平台提供更高性能的实现。这样的实现将与开源 Clang 中的实现 ABI 不兼容,因此我们不会支持 thread_local,直到我们在可预见的未来获得可以接受的实现。
A subsequent post confirms that thread_local
is still not supported in Xcode 6.3.
随后的帖子确认thread_local
Xcode 6.3 仍然不支持。
回答by sbooth
According to http://clang.llvm.org/cxx_status.html:
根据http://clang.llvm.org/cxx_status.html:
thread_local support currently requires the C++ runtime library from g++-4.8 or later
thread_local 支持当前需要来自 g++-4.8 或更高版本的 C++ 运行时库
I believe that the homebrew version of clang uses a different C++ runtime.
我相信 clang 的自制版本使用不同的 C++ 运行时。