2015-10-01 13 views
5

要約:/clangは '弱い'属性をサポートしていますか?弱リンクのllvm/clangは '弱い'属性をサポートしていますか?

私はいくつかのArduinoライブラリのソースを学んでいる(HardwareSerial.cppは、より詳細であることを)と私は前に使ったことがない、いくつかの興味深い属性weak見つけた:私はそれを見つけた

#if defined(HAVE_HWSERIAL0) 
    void serialEvent() __attribute__((weak)); 
    bool Serial0_available() __attribute__((weak)); 
#endif 

を面白いと私はそれが定義されていない場合はNULLに設定する必要がありますリンカーを読んだ。

私のテストではclangと私はそれを使用することができません。

lib.cpp:

#include "lib.h" 
#include <stdio.h> 

void my_weak_func() __attribute__((weak)); 

void lib_func() { 
    printf("lib_func()\n"); 

    if (my_weak_func) 
     my_weak_func(); 
} 

lib.h:

#ifndef LIB_FUNC 
#define LIB_FUNC 

void lib_func(); 

#endif 

main.cppに:

#include "lib.h" 
#include <stdio.h> 

#ifdef DEFINE_WEAK 
void my_weak_func() { 
    printf("my_weak_func()\n"); 
} 
#endif 

int main() { 

    lib_func(); 

    printf("finished\n"); 
    return 0; 
} 

私はg++ lib.cpp main.cpp -o main -DDEFINE_WEAKを使用する場合、私はそれを使用することができるよ:

MBA-Anton:Weak_issue asmirnov$ ./main 
lib_func() 
my_weak_func() 
finished 

が、私はg++ lib.cpp main.cpp -o mainを使用する場合、私はアプリリンクすることができませんでしだ:打ち鳴らすに関するより詳細なことには

Undefined symbols for architecture x86_64: 
    "my_weak_func()", referenced from: 
     lib_func() in lib-ceb555.o 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

を:

MBA-Anton:Weak_issue asmirnov$ g++ --version 
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/c++/4.2.1 
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) 
Target: x86_64-apple-darwin14.3.0 
Thread model: posix 

私は何をすべき? llvm/clangはweak属性をサポートしていますか?

PS。 (私が言うことができるように最善)は、弱いリンクのAppleの説明は誤解を招くようです

#include "lib.h" 
#include <stdio.h> 

extern void my_weak_func() __attribute__((weak_import)); 

void lib_func() { 
    printf("lib_func()\n"); 

    if (my_weak_func != NULL) 
     my_weak_func(); 
} 
+0

どのxcodeのバージョンを使用していますか( 'xcodebuild -version')? OSXのどのバージョン( 'sw_vers')? – Alec

+0

MBA-Anton:avr-clang asmirnov $ xcodebuild -version Xcode 7.2 ビルドバージョン7C68 – 4ntoine

答えて

4

:私はすでに道Apple describesにlib.cppを書き換え、まだ同じリンカエラーしようとしました。私は定義がリンク時に実際に利用可能である場合、weak/weak_importとして関数をマークするだけで成功しました。これはリンク時に弱くリンクされたシンボルを定義する必要がない通常のLinuxの動作とは逆です。打ち鳴らすと

例えば、GCC 4.8.2とUbuntuの14.04で、次のコンパイルではなく、OS X 10.9.5上

/* test.c */ 
int weakfunc() __attribute__((weak)); 

int main() 
{ 
    if (weakfunc) return weakfunc(); 
    else  return -1; 
} 

私が見つけた最も簡単な回避策は、明示的にリンカに伝えることです問題のシンボルを未定義のままにします。たとえば、clang test.c -Wl,-U,_myfuncです。シンボルの名前はCとC++で異なることに注意してください。 Cでは(少なくとも私にとって、これは一貫していると仮定します)、シンボル名の前にアンダースコアが付いています。 C++では、名前が変更されているので、__Z8weakfuncvのようなものが得られます(必ずしも一貫しているわけではありません)。私のUbuntuボックスに表示されている名前のアンダースコアが1つしかありません。

この方法に従うと、関数が実行時に定義されている場合(例えば、環境変数DYLD_INSERT_LIBRARIESを設定してライブラリをプリロードする場合や、共有ライブラリ依存性のバージョンが実行時とビルド時とで異なる場合)解決され、関数は必要に応じて呼び出されます。シンボルが実行時に定義されていない場合は、関数のチェックが失敗し、必要に応じて-1が返されます。

多少複雑な解決策は、問題の機能の実装を提供するダミーライブラリとリンクすることです。たとえば、同じディレクトリ内にlibdummy.dylibとして、次のコンパイル場合:あなたは弱いそれ

clang test.c -weak_library ./libdummy.dylib -flat_namespace

シンボルが、リンク時に定義されるにリンクすることができます

int weakfunc() 
{ 
    return 1; 
} 

ので、リンカは満足しており、生成されたバイナリに弱くリンクされているとマークされます。標準-l/-Lのリンクではなくlibdummy.dylibを-weak_libraryにリンクすると、ライブラリの依存関係自体が弱くなるため、実行時にlibdummy.dylibが使用できない場合でも実行可能ファイルが実行されます。

引数は、リンカに対して、「2レベル」の名前空間ではなく「フラット」な名前空間を使用するように指示します。これはOS Xのデフォルトの設定です。2レベルの名前空間では、 libdummy.dylibというライブラリからのバージョンのweakfuncのみを受け入れます。シンボルを未定義としてマークする最初のケースでは、シンボルがフラットな名前空間からのものとして扱われるは、リンカは実行時にどのライブラリが存在するのかわからないので注意してください。

+0

これは、Clangが弱いリンクやバグを実際にサポートしていないと思うようになります。 – 4ntoine

+1

バグがあると私は思っていますが、それはclangではなくldのOS Xバージョンにあります。生成されたバイナリ( 'dyldinfo -build a.out')を調べると、これらの回避策のいずれかで、シンボルが"弱い読み込み "として表示されると思います。問題は、ビルド時に定義されていない弱いインポートシンボルをldが正しく処理しないことです。 – Alec

+0

おかげさまで、 '-Wl、-U、_myfunc'がうまくいきます!ちょうどXcodeからそれを設定する方法を理解するのに少し時間がかかりました。それは '-Wl、-U、_myfunc'を" Other Linker Flags "に追加することです。 – Elist

関連する問題