为什么苹果铛禁用C ++ 11 thread_local时,'官方'clang支持它 [英] Why does Apple clang disallow C++11 thread_local when 'official' clang supports it

查看:1970
本文介绍了为什么苹果铛禁用C ++ 11 thread_local时,'官方'clang支持它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是一个简单的程序,使用共享库中非POD类型的C ++ 11 thread_local变量进行测试。



如果我使用自制的ang工作正常:

 > /usr/local/Cellar/llvm/3.5.0_2/bin/clang --version 
clang version 3.5.0(tags / RELEASE_350 / final)
目标:x86_64-apple-darwin14.0.0
线程模型: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 ++
- C编译器标识是Clang 3.5.0
- CXX编译器标识是Clang 3.5.0
- 检查工作C编译器使用:Ninja
- 检查工作C编译器使用:Ninja - works
- 检测C编译器ABI信息
- 检测C编译器ABI信息 - 完成
- 检查CXX编译器是否正常工作:Ninja
- 检查用于工作CXX编译器使用:Ninja - works
- 检测CXX编译器ABI信息
- 检测CXX编译器ABI信息 - 完成
- 配置完成
- 生成完成
> ninja all
...

> ./main
XXX生命周期::生命周期0x7fedc0c04b90
X前:-17
XXX生命周期::生命周期0x7fedc0c04c10
X之前的线程:-17
X后thread:2
XXX LifeCycle ::〜LifeCycle 0x7fedc0c04c10
X after:1
XXX生命周期::〜LifeCycle 0x7fedc0c04b90

但是,如果我尝试使用Apple Clang,则会收到一条错误消息,指出它不受支持:

 > / usr / bin / clang --version 
Apple LLVM版本6.0(clang-600.0.56)(基于LLVM 3.5svn)
目标:x86_64-apple-darwin14.0.0
线程模型:posix
> cmake .. -G Ninja -DCMAKE_C_COMPILER = / usr / bin / clang -DCMAKE_CXX_COMPILER = / usr / bin / clang ++
- C编译器标识为AppleClang 6.0.0.6000056
- CXX编译器标识AppleClang 6.0.0.6000056
- 检查工作C编译器使用:Ninja
- 检查工作C编译器使用:Ninja - works
- 检测C编译器ABI信息
- 检测C编译器ABI info - done
- 检查CXX编译器是否正常工作:Ninja
- 检查CXX编译器是否正常工作
- 检测CXX编译器ABI info
- 检测CXX编译器ABI信息 - 完成
- 配置完成
- 生成完成
- 生成文件已写入:

。 ninja all
[1/4]构建CXX对象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.od -o CMakeFiles / lib.dir / lib。 cpp.o -c ../lib.cpp
../lib.cpp:23:5:错误:当前目标不支持线程本地存储
thread_local LifeCycle lc;
^
生成了1个错误。
ninja:build stopped:子命令失败。

任何人都可以提供任何洞察,为什么苹果的clang变体懦弱拒绝荣誉thread_local,尽管事实底层编译器支持它,并且生成的代码似乎工作?



lib.h:



< #pragma once

int doit(int)__attribute __((__ visibility __(default)));

lib.cpp:

  #includelib.h

#include< thread>
#include< cstdlib>
#include< cstdio>

namespace {

class LifeCycle {
public:
LifeCycle()
:x(-17){
printf (XXX LifeCycle :: LifeCycle%p \\\
,this);
}

〜LifeCycle(){
printf(XXX LifeCycle ::〜LifeCycle%p\\\
,this);
}

int x;
};

thread_local生命周期lc;
} //命名空间

int doit(int arg){
printf(X before:%d\\\
,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\\\
,lc.x);
});
xwriter.join();
printf(X after:%d\\\
,lc.x);
return(lc.x == arg?EXIT_SUCCESS:EXIT_FAILURE);
}

main.cpp:

  #includelib.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)


解决方案

UPDATE: Xcode 8 Beta和GM版本中包含的clang编译器支持C ++ 11 thread_local 关键字。此功能已在 WWDC 2016视频LLVM新功能中讨论过,从5:50开始。 (翻译



问题列表中的示例程序编译并运行与Xcode 8 GM在OS X 10.11.6,并产生预期的输出。






对于Xcode 7.x及更早版本,这里是从2014年起的答案 Apple开发人员论坛上的Apple工程师:


我们不支持从开源的
Clang的thread_local实现,因为我们相信我们可以为我们的平台提供更高性能的
实现,使用动态
链接器中的各种功能。这样的实现将与ABI不兼容的开源Clang中的
实现,所以我们不会支持
thread_local,直到我们得到一个实现,我们可以为
可预见的未来生活。


后续帖子确认Xcode 6.3中仍然不支持 thread_local


Below is a simple program that tests using a C++11 thread_local variable of non-POD type in a shared library.

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:

> /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?

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)

解决方案

UPDATE: The clang compiler included with the Xcode 8 Beta and GM releases supports the C++11 thread_local keyword. This capability was discussed in the WWDC 2016 video "What's New in LLVM", beginning at the 5:50 mark. (transcript)

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.


For Xcode 7.x and earlier, here is an answer from 2014 from an Apple engineer on the 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.

A subsequent post confirms that thread_local is still not supported in Xcode 6.3.

这篇关于为什么苹果铛禁用C ++ 11 thread_local时,'官方'clang支持它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆